如何在 Oracle 中编写长 group by/case 子句?

Posted

技术标签:

【中文标题】如何在 Oracle 中编写长 group by/case 子句?【英文标题】:How to code long group by/case clauses in Oracle? 【发布时间】:2012-10-28 19:20:40 【问题描述】:

我经常有一些查询要按 case 子句进行分组,例如:

SELECT
    CASE WHEN FIELD IS NULL                     |
    AND (SOMETHING > 100 OR SOMETHINGELSE < 50) |
    AND THATDATE >= add_months(sysdate, -4)     | -> Case
        THEN 0 ELSE 1                           |                                                               
    END AS dim_1,                               |                                                               
    dim_2,
    sum(SOMEFIELD_TOTAL) as measure_1
FROM MY_TABLE
GROUP BY
    CASE WHEN FIELD IS NULL                     | 
    AND (SOMETHING > 100 OR SOMETHINGELSE < 50) | 
    AND THATDATE >= add_months(sysdate, -4)     | -> Same case
        THEN 0 ELSE 1                           |                                                                
    END,                                        |                                                                
    dim_2

有没有办法可以将我为整个案例定义的别名用于group by,例如group by dim_1

找到this explanation,还是想知道有没有出路。

【问题讨论】:

【参考方案1】:

我认为您过于担心重复表达。 Oracle 和任何其他 DBMS 都会将该表达式识别为重复项并仅计算一次。如果您只是不想重复它(这只是 剪切和粘贴 琐事提醒您),您可以使用派生表或公用表表达式。

SELECT 
    dim_1, dim_2, sum(SOMEFIELD_TOTAL) as measure_1
FROM (
    SELECT
        CASE WHEN FIELD IS NULL                     |
        AND (SOMETHING > 100 OR SOMETHINGELSE < 50) |
        AND THATDATE >= add_months(sysdate, -4)     | -> Case
            THEN 0 ELSE 1                           |                                                               
        END AS dim_1,                               |                                                               
        dim_2,
        SOMEFIELD_TOTAL
    FROM MY_TABLE
) AS SQ
GROUP BY
    dim_1, dim_2

看起来并没有好多少,是吗?

【讨论】:

嗯,一般来说我会同意你的。我更关心代码,真的。这个例子很简单,但有时我真的有很长的cases 并且在同一个句子中不止一个。尽管正如您所说,这一切都归结为剪切和粘贴,但当代码变长时,它始终是拼写错误和愚蠢错误的地方。无论如何,您输入的语法将来可能会有所帮助。谢谢。【参考方案2】:

您可以使用subquery factoring 也称为named subquerycommon table expression (CTE)(感谢@a_horse_with_no_name)

WITH t as 
(
SELECT
    CASE WHEN FIELD IS NULL                     
    AND (SOMETHING > 100 OR SOMETHINGELSE < 50) 
    AND THATDATE >= add_months(sysdate, -4)     
        THEN 0 ELSE 1 END AS dim_1,         
    dim_2,
    SOMEFIELD_TOTAL as measure_1
FROM MY_TABLE
)
SELECT dim_1, dim_2, sum(SOMEFIELD_TOTAL)
FROM t
GROUP BY dim_1, dim_2

这种方法的优点是你可以有很多子查询,而不必像在常规子查询中那样加入它们(内部选择)

【讨论】:

附带说明:此功能的“官方”名称(根据 ANSI SQL 标准)是“公用表表达式”(或 CTE)

以上是关于如何在 Oracle 中编写长 group by/case 子句?的主要内容,如果未能解决你的问题,请参考以下文章

如何在以下场景中使用 Oracle Group BY

如何使用 ORACLE GROUP BY?

oracle查询选择语句——count、sum、order by、group by

oracle中group by用法

leetcode查找重复的电子邮箱——oracle的group by 和having组合使用

oracle group by 性能优化