MySQL Query - 使用group-by时丢失记录

时间:2009-01-12 05:59:29

标签: sql mysql group-by

我有一个问题:

select score, count(1) as 'NumStudents' from testresults where testid = 'mytestid'
group by score order by score

其中testresults表包含测试中学生的表现。假设测试的最大标记为10,样本结果如下所示。

  

得分,NumStudents

     

0 10
1 20
2 12
3 5
5 34
..×10 23

正如您所看到的,此查询不会返回任何学生没有得分的记录。例如。没有人在测试中得分为4/10,并且在查询输出中没有得分= 4的记录。

我想更改查询,以便我可以使用0作为NumStudents字段的值来获取这些丢失的记录。这样我的最终输出就会有最多+1个记录,每个记录对应一个记录。

有什么想法吗?

修改

数据库包含多个测试,测试的最大标记是测试定义的一部分。因此,拥有一个用于存储所有可能分数的新表是不可行的。从某种意义上说,每当我使用新的最大标记创建新测试时,我都需要确保更新新表以包含这些分数。

4 个答案:

答案 0 :(得分:2)

SQL擅长处理数据库中的数据集,但对数据库中的数据集不太好。

最佳解决方法是为您需要的值保留一个小表:

CREATE TABLE ScoreValues (score int);
INSERT INTO ScoreValues (score) 
  VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);

鉴于您在另一个表中定义测试的最大标记的评论,您可以通过以下方式加入该表,只要ScoreValues确定值至少高于或高于最大考试的最大分数:

SELECT v.score, COUNT(tr.score) AS 'NumStudents'
FROM ScoreValues v 
  JOIN Tests t ON (v.score <= t.maxmarks)
  LEFT OUTER JOIN TestResults tr ON (v.score = tr.score AND t.testid = tr.testid)
WHERE t.testid = 'mytestid'
GROUP BY v.score;

答案 1 :(得分:1)

最明显的方法是创建一个名为“Scores”的表,然后将表外部连接到表中。

SELECT s.score,COUNT(1)AS scoreCount
从得分AS s LEFT OUTER JOIN testScores AS ts
ON s.score = ts.score
GROUP BY s.score

如果您不想创建表格,可以使用

选择
  1作为分数,SUM(CASE WHEN ts.score = 1 THEN 1 ELSE 0 END)AS scoreCount,
  2作为分数,SUM(CASE WHEN ts.score = 2 THEN 1 ELSE 0 END)AS scoreCount,
  3作为分数,SUM(当ts.score = 3然后1 ELSE 0 END时的情况)AS scoreCount,
  4作为分数,SUM(CASE WHEN ts.score = 4 THEN 1 ELSE 0 END)AS scoreCount,
  ...   10作为分数,SUM(当ts.score = 10然后1 ELSE 0 END时)作为scoreCount
来自testScores AS ts

答案 2 :(得分:0)

MySQL是否支持设置返回功能? PostgreSQL的最新版本有一个函数generate_series(start, stop),第一行产生值start,第二行产生start+1,依此类推stop stop第1行。这样做的好处是你可以将这个函数放在FROM子句中的子选择中,然后加入它,而不是像le dorfier和Bill Karwin所建议的那样创建和填充表并加入它。

答案 3 :(得分:0)

就像一次心理练习一样,我想出了这个,以便在MySQL中生成一个序列。只要方块上的所有数据库中的表的数量小于序列的总长度,它就会起作用。我不会推荐它用于生产;)

SELECT @n:=@n+1 as n from (select @n:=-1) x, Information_Schema.Tables y, Information_Schema.Tables WHERE @n<20; /* sequence from 0 to 20 inclusive */