GROUP BY子句之后的Oracle CONNECT BY子句
我刚刚在这里碰到了这篇有趣的文章,展示了如何在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
子句之后。 根据规范,这应该是不可能的。 我试过这个使用简单的查询,它确实有效,但! 以下两个查询返回相同的结果:
-- 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;
这是一个无证的功能吗? 或者为了方便,只是语法冷漠? 或者这两个陈述巧妙地表现不同?
我认为这只是一个无关紧要的语法差异。
更具体地说,我认为这是一个文档错误。 8i的语法图意味着支持任一顺序。 8i参考文献中没有任何内容暗示顺序有什么不同。 但是这个图也意味着你可以有多个group_by_clause
或hierarchical_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语法:
看看执行计划。 在我的环境中,它们是相同的,通过CONNECT BY操作进入哈希群组。 所以看起来,首先放置GROUP BY只是一种奇怪的语法,可以产生与更自然排序相同的结果。
从技术上讲,这可能是解析器中的一个错误,因为正如你所说规范指出,层次查询子句应该在group-by子句之前。 但是在查询执行方式上似乎没有任何区别。
链接地址: http://www.djcxy.com/p/58857.html上一篇: Oracle CONNECT BY clause after GROUP BY clause
下一篇: How can I suspend appstats for a single request on App Engine/Java?