4

我有一张桌子:

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?谢谢。^^

4

2 回答 2

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您在问题中建议的 a 。首先它将每个数字等级解析为相应的字母等级,然后DISTINCT删除重复项。最后,它将数据洗牌成列。

于 2012-07-30T05:06:09.570 回答
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;
于 2012-07-30T04:59:01.207 回答