MySQL Query - 使用 group-by 时获取丢失的记录
Posted
技术标签:
【中文标题】MySQL Query - 使用 group-by 时获取丢失的记录【英文标题】:MySQL Query - getting missing records when using group-by 【发布时间】:2010-09-30 21:05:20 【问题描述】:我有一个问题:
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 条记录,每个可能的分数都有一条。
有什么想法吗?
编辑:
数据库包含多个测试,测试的最高分数是测试定义的一部分。所以有一个新的表来存储所有可能的分数是不可行的。从某种意义上说,每当我创建一个新的最高分数的新测试时,我需要确保新表也应该更改为包含这些分数。
【问题讨论】:
【参考方案1】: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;
【讨论】:
【参考方案2】:最明显的方法是创建一个名为“Scores”的表并将您的表左外部连接到它。
SELECT s.score, COUNT(1) AS scoreCount FROM 分数 AS s 左外连接 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(当 ts.score = 3 THEN 1 ELSE 0 END 时的情况)作为 scoreCount, 4 作为分数,SUM(当 ts.score = 4 THEN 1 ELSE 0 END 时的情况)作为 scoreCount, ... 10 作为分数,SUM(CASE WHEN ts.score = 10 THEN 1 ELSE 0 END) 作为 scoreCount FROM testScores AS ts
【讨论】:
@le dorfier:是的,一般来说这会起作用。但在我的具体情况下,测试的最高分数是测试定义的一部分,当有大量不同最高分数的测试时,有一个表来存储所有可能的分数是不可行的。 你最好把问题记录得更完整。很难想象可能的分数范围超出了定制表的容量的真实情况。【参考方案3】:mysql 是否支持 set-returning 函数? PostgreSQL 的最新版本有一个函数generate_series(start, stop)
,它在第一行产生值start
,在第二行产生start+1
,依此类推,直到stop
th 行产生stop
。这样做的好处是您可以将此函数放在 FROM
子句中的子选择中,然后加入它,而不是按照 le dorfier 和 Bill Karwin 的建议创建和填充表并加入到该表中。
【讨论】:
很遗憾,MySQL 不支持这种功能。【参考方案4】:作为一个心理练习,我想出了这个在 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 */
【讨论】:
以上是关于MySQL Query - 使用 group-by 时获取丢失的记录的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法提示 mysql 使用 Using index for group-by
使用嵌套的 group-by/having 子句进行复杂连接?
如何在单个级别上添加新列时使用 pandas group-by?