【问题标题】:Oracle CONNECT BY clause after GROUP BY clauseGROUP BY 子句后的 Oracle CONNECT BY 子句
【发布时间】:2012-04-20 01:39:37
【问题描述】:

我刚刚遇到过这个interesting article here,展示了如何在Oracle 中使用分层查询和窗口函数模拟wm_concat()group_concat()

SELECT deptno,
       LTRIM(MAX(SYS_CONNECT_BY_PATH(ename,','))
       KEEP (DENSE_RANK LAST ORDER BY curr),',') AS employees
FROM   (SELECT deptno,
               ename,
               ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) AS curr,
               ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) -1 AS prev
        FROM   emp)
GROUP BY deptno
CONNECT BY prev = PRIOR curr AND deptno = PRIOR deptno
START WITH curr = 1;

虽然我发现这不是一个可读性很强的解决方案,但它非常有趣,特别是因为CONNECT BY .. STARTS WITH 子句 GROUP BY 子句之后。根据the specification,这应该是不可能的。我已经使用一个简单的查询尝试过这个,但它确实有效!以下两个查询返回相同的结果:

-- wrong according to the specification:
select level from dual group by level connect by level <= 2;
-- correct according to the specification:
select level from dual connect by level <= 2 group by level;

这是一个未记录的功能吗?或者只是为了方便起见语法冷漠?或者这两个语句的行为是否有细微的不同?

【问题讨论】:

    标签: sql oracle select syntax hierarchical-query


    【解决方案1】:

    我认为这只是一个微不足道的语法差异。

    更具体地说,我认为这是一个文档错误。 8i 的语法图暗示支持任一顺序。 8i reference 中的任何内容都没有暗示订单有任何区别。但该图也暗示您可以拥有多个 group_by_clausehierarchical_query,这是不正确的:

    --You can't group twice: ORA-01787: only one clause allowed per query block
    select level from dual connect by level <= 2 group by level group by level;
    

    我的猜测是,当 Oracle 修复 9i 的语法图时,他们也忘记了顺序可能不同。或者他们可能故意忽略它,因为先做分层部分似乎更合乎逻辑。

    像这样的一些小的语法变化没有记录在案。我不认为这意味着它们不受支持。甲骨文可能后悔允许这么多奇怪的选择,并希望事情至少看起来简单。例如,HAVING 可以在 GROUP BY 之前出现,许多旧的并行功能仍然有效(但被忽略)等等。(这就是为什么当人们说他们要快速“解析 SQL”时我总是笑——好祝你好运!)

    Oracle 8i 语法:

    Oracle 9i 语法:

    【讨论】:

    【解决方案2】:

    查看执行计划。在我的环境中,它们是相同的,将 CONNECT BY 操作输入 HASH GROUP BY。因此,将 GROUP BY 放在首位似乎只是一种奇怪的语法,它产生的结果与更自然的排序相同。

    从技术上讲,这可能是解析器中的一个错误,因为正如您所说,规范表明分层查询子句应该在 group-by 子句之前。但它似乎对查询的执行方式没有任何影响。

    【讨论】:

    • 很好的提示。我也认为这是解析器的一个错误(或“隐藏功能”)。但是,这是一个微不足道的查询,执行计划(甚至结果)在更复杂的查询中仍然可能有所不同...
    猜你喜欢
    • 1970-01-01
    • 2021-08-15
    • 2022-01-13
    • 2018-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    相关资源
    最近更新 更多