0

我有一个查询:

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,并且查询输出中没有 score = 4 的记录。

我想更改查询,以便我可以获取这些缺失记录,其中 0 作为 NumStudents 字段的值。这样我的最终输出将有 max + 1 条记录,每个可能的分数都有一条。

有任何想法吗 ?

编辑:

数据库包含几个测试,测试的最高分数是测试定义的一部分。所以有一个新的表来存储所有可能的分数是不可行的。从某种意义上说,每当我创建一个新的最高分数的新测试时,我需要确保新表也应该更改为包含这些分数。

4

4 回答 4

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;
于 2009-01-12T06:07:52.183 回答
1

最明显的方法是创建一个名为“Scores”的表并将您的表左外部连接到它。

SELECT s.score, COUNT(1) AS scoreCount
FROM score 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) 作为 scoreCount,
2 作为分数,SUM(CASE WHEN ts.score = 2 THEN 1 ELSE 0 END) 作为 scoreCount,
3 作为分数,SUM (CASE WHEN ts.score = 3 THEN 1 ELSE 0 END) AS scoreCount,
4 as score, SUM(CASE WHEN ts.score = 4 THEN 1 ELSE 0 END) AS scoreCount,
... 10 as score, SUM(CASE WHEN ts.score = 10 THEN 1 ELSE 0 END) AS scoreCount
FROM testScores AS ts

于 2009-01-12T06:03:54.500 回答
0

MySQL 是否支持 set-returning 函数?PostgreSQL 的最新版本有一个函数,generate_series(start, stop)start在第一行,start+1第二行,依此类推,直到stopstopth 行。这样做的好处是您可以将此函数放在FROM子句中的子选择中,然后加入它,而不是像 le dorfier 和 Bill Karwin 建议的那样创建和填充表并加入表。

于 2009-01-12T07:48:19.347 回答
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 */
于 2009-01-12T13:38:57.967 回答