【问题标题】:SQL return data where low score is less than average low score?SQL返回低分低于平均低分的数据?
【发布时间】:2018-03-17 15:08:18
【问题描述】:

我有一个关于家庭作业的问题,我需要列出那些低分低于平均低分的测验的测验编号和日期。

为此,我需要使用 GROUP BY 子句和 HAVING 子句。它应该看起来像这样:

select quiznum, quizdate
from quizzes
group by quiznum, quizdate, lowscore 
having lowscore < avg(lowscore);

然而,这会返回未找到的数据。

如果我手动输入平均分(大约为 14),它会重新计算我需要的信息,但关于这个问题,我不知道平均低分。

如何列出低分低于平均低分的测验编号和日期?

【问题讨论】:

  • 提示:HAVING 子句中需要子查询,外部查询中不需要聚合。
  • 发布带有示例数据和所需输出的 ​​DDL
  • 作业认为什么是“低分”?测验表中是否有“分数”列?您是否需要首先找到低分,或者此表是否仅包含名为“lowscore”的列,而您只需要找到低于 lowscore 列中值平均值的分数?请解释一下,因为如果要帮助您解答这些难题,这些部分很重要。

标签: sql group-by having


【解决方案1】:

我想这个查询可能对你有用。

您需要创建一个子查询来获取avg 的分数。然后join self 并进行比较。

SELECT T2.* 
FROM 
(
    SELECT quiznum, 
       quizdate,
       avg(lowscore) as avgScore
    FROM quizzes
    group by quiznum, quizdate
) T1 INNER JOIN quizzes T2 
ON 
    T1.quiznum = T2.quiznum 
AND 
    T1.quizdate = T2.quizdate
Where T2.lowscore < T1.avgScore

【讨论】:

    【解决方案2】:

    在这种情况下,我发现使用分析窗口函数来完成所需的输出更容易。在我的查询中获得所需输出的关键是:

    AVG(score) OVER (PARTITION BY quiznum, quizdate) AS avg_score

    完成这项工作的查询如下。我正在使用 WITH 子句来创建虚假数据,但不要让您感到困惑。 BASE 查询是您所需要的。 WITH 子句只是在这里创建一个包含要处理的数据的假表。

    WITH demo_data AS
    (
      SELECT    1001     AS quiznum,    '10-JAN-18'  AS quizdate,   91   AS score    FROM dual UNION ALL
      SELECT    1001     AS quiznum,    '10-JAN-18'  AS quizdate,   75   AS score    FROM dual UNION ALL
      SELECT    1001     AS quiznum,    '10-JAN-18'  AS quizdate,   35   AS score    FROM dual UNION ALL
      SELECT    1001     AS quiznum,    '10-JAN-18'  AS quizdate,   40   AS score    FROM dual UNION ALL
      SELECT    1001     AS quiznum,    '10-JAN-18'  AS quizdate,   70   AS score    FROM dual UNION ALL
      SELECT    1001     AS quiznum,    '10-JAN-18'  AS quizdate,   85   AS score    FROM dual UNION ALL
      SELECT    1002     AS quiznum,    '17-JAN-18'  AS quizdate,   35   AS score    FROM dual UNION ALL
      SELECT    1002     AS quiznum,    '17-JAN-18'  AS quizdate,   40   AS score    FROM dual UNION ALL
      SELECT    1002     AS quiznum,    '17-JAN-18'  AS quizdate,   70   AS score    FROM dual UNION ALL
      SELECT    1002     AS quiznum,    '17-JAN-18'  AS quizdate,   85   AS score    FROM dual
    )
    SELECT quiznum, quizdate, score, avg_score
    FROM
    (
      SELECT quiznum, quizdate, score, AVG(score) OVER (PARTITION BY quiznum, quizdate) AS avg_score
      FROM demo_data
    )
    WHERE score < avg_score
    ;
    

    下图按测验编号和日期显示了所有数据,并告诉我们平均分数。我们可以通过用外部 Select 包装它来使用它,这样我们就可以在 WHERE 子句中添加一个过滤器,以便将分数与平均分数进行比较。

    下图显示了在 WHERE 子句中添加过滤器后的样子:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-16
      • 1970-01-01
      • 2020-08-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多