【问题标题】:MySQL Query - getting missing records when using group-byMySQL Query - 使用 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 条记录,每个可能的分数都有一条。

有什么想法吗?

编辑:

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

【问题讨论】:

    标签: sql mysql group-by


    【解决方案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,依此类推,直到stopth 行产生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 */
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-19
        • 1970-01-01
        • 1970-01-01
        • 2022-08-11
        • 1970-01-01
        • 2018-03-29
        相关资源
        最近更新 更多