GROUP BY子句之后的Oracle CONNECT BY子句

时间:2012-04-06 12:24:28

标签: sql oracle select syntax hierarchical-query

我刚刚遇到了这个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子句后出现。根据{{​​3}},这是不可能的。我尝试使用一个简单的查询,但它确实有效!以下两个查询返回相同的结果:

-- 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;

这是一个无证件的功能吗?或者只是方便的语法冷漠?或者这两个陈述巧妙地表现得不同?

2 个答案:

答案 0 :(得分:2)

查看执行计划。在我的环境中,它们是相同的,CONNECT BY操作输入HASH GROUP BY。所以看起来首先放置GROUP BY只是一种奇怪的语法,它产生的结果与更自然的顺序相同。

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

答案 1 :(得分:2)

我认为这只是一个无关紧要的语法差异。

更具体地说,我认为这是一个文档错误。 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的语法图时,他们也忘了订单可能会有所不同。或者他们可能故意将其排除在外,因为首先执行分层部分似乎更合乎逻辑。

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

Oracle 8i语法: Oracle 8i SELECT syntax

Oracle 9i语法: Oracle 9i SELECT syntax