MySQL查询-使用group by时获取丢失的记录

MySQL查询-使用group by时获取丢失的记录,sql,mysql,group-by,Sql,Mysql,Group By,我有一个问题: 其中testresults表包含学生在测试中的表现。假设测试的最大分数为10,示例结果如下所示 分数,NUM学生 010120212355341023 如您所见,此查询不会返回任何学生未得分的记录。例如,没有人在测试中得分为4/10,查询输出中没有得分=4的记录 我想更改查询,以便可以获取这些丢失的记录,其中NumStudents字段的值为0。这样,我的最终输出将有最多+1个记录,每个可能的分数对应一个记录 有什么想法吗 编辑: 数据库包含多个测试,测试的最大分数是测试定义的一部

我有一个问题:

其中testresults表包含学生在测试中的表现。假设测试的最大分数为10,示例结果如下所示

分数,NUM学生

010
120
212
35
534

1023

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

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

有什么想法吗

编辑:


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

最明显的方法是创建一个名为“Scores”的表,并将您的表与之连接

选择s.score,计数(1)作为scoreCount
从作为s的分数开始
左外连接测试分数为ts
在s.score=ts.score
按s分数分组

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

选择
1作为分数,求和(当ts.score=1时,则1为0结束)作为分数计数,
2作为分数,求和(当ts.score=2,则1为0)作为分数计数,
3作为分数,求和(当ts.score=3时,则为1,否则为0)作为分数计数,
4作为分数,求和(如果ts.score=4,则1为0)作为分数计数,
... 10作为分数,求和(当ts.score=10时,则为1,否则为0结束)作为分数计数

从testScores AS ts

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

选择s.score,计数(1)作为scoreCount
从作为s的分数开始
左外连接测试分数为ts
在s.score=ts.score
按s分数分组

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

选择
1作为分数,求和(当ts.score=1时,则1为0结束)作为分数计数,
2作为分数,求和(当ts.score=2,则1为0)作为分数计数,
3作为分数,求和(当ts.score=3时,则为1,否则为0)作为分数计数,
4作为分数,求和(如果ts.score=4,则1为0)作为分数计数,
... 10作为分数,求和(当ts.score=10时,则为1,否则为0结束)作为分数计数

从testScores AS ts来看,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;
选择v.score,将(tr.score)计数为“numstudent”
来自ScoreV

连接测试t ON(v.scoreSQL擅长处理数据库中的数据值集,但不擅长处理数据库中不存在的数据值集

最好的解决方法是保留一个小表格,用于显示需要设置范围的值:

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;
选择v.score,将(tr.score)计数为“numstudent”
来自ScoreV

加入测试t ON(v.scoreMySQL是否支持set返回函数?PostgreSQL的最新版本有一个函数,
generate_series(start,stop)
在第一行生成值
start
,在第二行生成值
start+1
,依此类推,直到
stop
第四行生成值
stop
。这样做的好处是,您可以将此函数放在
FROM
子句的子选择中,然后连接到它,而不是创建并填充表和连接正如le dorfier和Bill Karwin所建议的那样。

MySQL是否支持设置返回函数?PostgreSQL的最新版本有一个函数,
generate\u series(start,stop)
在第一行生成值
start
,在第二行生成值
start+1
,依此类推,直到
stop
第四行生成值
stop
。这样做的好处是,您可以将此函数放在
FROM
子句的子选择中,然后连接到它,而不是创建并填充表和连接正如le dorfier和Bill Karwin所建议的那样。

作为一种心理练习,我提出了在MySQL中生成序列的方法。只要方格上所有数据库中的表数小于序列的总长度,它就可以工作。不过,我不建议将其用于生产;)


选择@n:=@n+1作为n from(选择@n:=-1)x,Information_Schema.Tables y,Information_Schema.Tables,其中@n作为一个心理练习,我想出了这个方法来在MySQL中生成一个序列。只要方框平方上所有数据库中的表数小于序列的总长度,它就可以工作。不过,我不建议将其用于生产;)


从(选择@n:=-1)x、信息\u Schema.Tables y、信息\u Schema.Tables中选择@n:=@n+1作为n@n@le多菲尔:是啊,一般来说,那会管用的。但在我的具体案例中,测试的最高分数是测试定义的一部分,当有大量的测试具有不同的最高分数时,使用一个表来存储所有可能的分数是不可行的