SQL:在SUM中使用DISTINCT

4

我有一个名为sometable的表:

name |test_date | score   
-----------------------
jon  |2012:07:01|   95   
jon  |2012:07:01|   60   
jon  |2012:07:01|   30   
alex |2012:07:01|   80   
alex |2012:07:01|   85   
alex |2011:05:01|   40  
emile|2011:01:01|   89    
我希望针对每个人获取一些行,并根据以下规则提供有关其score_grading的信息: score>79=A, 80>score>49=B, 否则为C。 问题在于,我希望:如果同一天有多个学生的score_grade相同,则它将被视为一个score_grade。 例如,在表格中,我们可以看到Alex在一天内获得了两次A,我希望它只计为1个A。 因此,结果将是
name |    A   |    B     |    C
jon  |    1   |    1     |    1
alex |    1   |    0     |    1  
emily|    1   |    0     |    0

我只会像这样的代码:

SELECT name,
SELECT SUM(IF(score)>79),1,0)) as A,
SELECT SUM(IF(80>score>49),1,0)) as B,
SELECT SUM(IF(score)<50),1,0)) as C from sometable group by name
Nha,我该如何在上面加上“DISTINCT”呢? 有人能给出解决方案吗?也许不需要使用DISTINCT? 谢谢。^^

2
如果他们在同一天得到不同的分数,例如一个 C 和一个 A,那该怎么办?显示两个?显示一个?哪一个? - Marc B
展示所有的数据。同一天内,相同人员的相同分数只计算一次。 - user1545296
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
2
你是指像以下这样的东西吗 (sqlfiddle)?
SELECT name, SUM(IF(A>=1,1,0)) as A, SUM(IF(B>=1,1,0)) as B, 
    SUM(IF(C>=1,1,0)) as C
FROM
(
    SELECT name, test_date, SUM(IF(score>79,1,0)) as A, 
        SUM(IF(score BETWEEN 49 AND 79,1,0)) as B, SUM(IF(score<50,1,0)) as C 
    FROM sometable 
    GROUP BY name, test_date
) daygroups
GROUP BY name

首先,在子查询中将您的数据随机排列成name,test_date,A,B,C行。然后外部查询将聚合这些行,如果当天至少有一个字母等级的分数,则取1,否则取0。


这个也应该行(sqlfiddle):

SELECT name, SUM(IF(lettergrade = 'A',1,0)) AS A, 
    SUM(IF(lettergrade = 'B',1,0)) AS B, SUM(IF(lettergrade = 'C',1,0)) AS C
FROM
(
    SELECT DISTINCT name, test_date, 
        CASE WHEN score>79 THEN 'A' 
             WHEN score BETWEEN 49 AND 79 THEN 'B' 
             ELSE 'C' 
        END AS lettergrade
    FROM sometable
) lettergrades
GROUP BY name

我不确定哪一个更好。这个查询使用了你在问题中建议的DISTINCT。首先,它将每个数字成绩解析为相应的字母成绩,然后去除重复项。DISTINCT最后将数据随机分配到列中。


哇,非常感谢。它们两个都可以, 我会学习它的逻辑。^^ - user1545296
当然可以。我为每个添加了解释,以帮助您理解它正在做什么。 - lc.

0

这应该可以工作:

SELECT name,
       SUM(IF(score > 79, 1, 0)) as A,
       SUM(IF(score BETWEEN 50 AND 79, 1, 0)) as B,
       SUM(IF(score < 50, 1, 0)) as C 
FROM   (SELECT DISTINCT name, score FROM sometable) a
GROUP BY name;

我认为当OP说“不同的分数”时,他们指的是按字母成绩而非数字。 - lc.
嗯,谢谢。^^ 但是,不幸的是它抛出了 姓名 | A | B | C 琼恩 | 1 | 1 | 1 亚历克斯 | 2 | 0 | 1
艾米丽| 1 | 0 | 0
- user1545296
抱歉,我的意思是不同的分数等级(字母),就像LC所说的那样。 - user1545296

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,