【问题标题】:SQL - Group count by 2 or more columns using union takes more than 2 secondsSQL - 使用联合对 2 个或更多列进行分组计数需要超过 2 秒
【发布时间】:2020-10-14 13:39:09
【问题描述】:

给定一张表,我们称之为 performance6a - 带表结构>> 学生ID |数学 |历史 |语言 |科学

table content - performance6a

我需要编写一个生成如下报告的查询 -

expected query output

组数基于2个类别,在这种情况下,通过或失败然后主题。

请注意,这些操作是在无法规范化或重新设计的系统表上执行的。两个类别的数量都可以增长(类别 - 通过/失败可以增加到 100 和类别 - 主题可以增加到 ~5k)

我尝试过的:

(SELECT 'PASS' AS STATUS, 'MATH', COUNT(ID) FROM PERFORMANCE6A WHERE MATH > 30) UNION
(SELECT 'FAIL' AS STATUS, 'MATH', COUNT(ID) FROM PERFORMANCE6A WHERE MATH <= 30) UNION
(SELECT 'PASS' AS STATUS, 'HISTORY', COUNT(ID) FROM PERFORMANCE6A WHERE HISTORY > 30) UNION
(SELECT 'FAIL' AS STATUS, 'HISTORY', COUNT(ID) FROM PERFORMANCE6A WHERE HISTORY <= 30) UNION
(SELECT 'PASS' AS STATUS, 'LANGUAGE', COUNT(ID) FROM PERFORMANCE6A WHERE LANGUAGE > 30) UNION
(SELECT 'FAIL' AS STATUS, 'LANGUAGE', COUNT(ID) FROM PERFORMANCE6A WHERE LANGUAGE <= 30) UNION
(SELECT 'PASS' AS STATUS, 'SCIENCE', COUNT(ID) FROM PERFORMANCE6A WHERE SCIENCE > 30) UNION
(SELECT 'FAIL' AS STATUS, 'SCIENCE', COUNT(ID) FROM PERFORMANCE6A WHERE SCIENCE <= 30);

这个查询给了我正确的输出,但是执行时间超过了 2 秒。 我正在寻找优化查询的想法。

【问题讨论】:

    标签: sql db2 system-tables


    【解决方案1】:

    如果您先取消透视然后聚合,它可能会更快:

    select (case when score > 30 then 'PASS' else 'FAIL' end) as status, subject, count(*)
    from ((select 'math' as subject, math as score from PERFORMANCE6A) union all
          (select 'history' as subject, history as score from PERFORMANCE6A) union all
          (select 'language' as subject, language as score from PERFORMANCE6A) union all
          (select 'science' as subject, science as score from PERFORMANCE6A)
         ) ss
    group by (case when score > 30 then 'PASS' else 'FAIL' end), subject
          
    

    【讨论】:

    • 谢谢@Gordon Linoff。它将执行时间降低到 ~800 毫秒
    【解决方案2】:

    试试这个:

    WITH PERFORMANCE6A (STUDENT_ID, MATH, HISTORY, LANGUAGE, SCIENCE) AS 
    (
    VALUES
      (1, 23, 42, 40, 35)
    , (2, 45, 21, 25, 36)
    , (3, 32, 12, 15, 27)
    , (4, 49, 45, 38, 31)
    , (5, 50, 43, 37, 41)
    )
    SELECT RESULT, NAME, COUNT(1) CNT
    FROM
    (
    SELECT 
      D.NAME
    , CASE
        WHEN D.NAME = 'MATH'     THEN CASE WHEN P.MATH     > 30 THEN 'PASS' ELSE 'FAIL' END 
        WHEN D.NAME = 'HISTORY'  THEN CASE WHEN P.HISTORY  > 30 THEN 'PASS' ELSE 'FAIL' END 
        WHEN D.NAME = 'LANGUAGE' THEN CASE WHEN P.LANGUAGE > 30 THEN 'PASS' ELSE 'FAIL' END 
        WHEN D.NAME = 'SCIENCE'  THEN CASE WHEN P.SCIENCE  > 30 THEN 'PASS' ELSE 'FAIL' END 
      END AS RESULT
    FROM PERFORMANCE6A P
    CROSS JOIN (VALUES 'MATH', 'HISTORY', 'LANGUAGE', 'SCIENCE') D (NAME)
    )
    GROUP BY RESULT, NAME
    ORDER BY RESULT, NAME;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-26
      • 1970-01-01
      相关资源
      最近更新 更多