我刚刚浏览了这个
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;
这是一个没有文档的功能吗?或者只是语法无差异以方便?或者这两个陈述巧妙地表现得不同?
解决方法
我认为这只是一个无关紧要的语法差异.
更具体地说,我认为这是一个文档错误. 8i的语法图表示支持任一顺序. 8i reference中没有任何内容暗示订单有任何区别.但是这个图表也暗示你可以有多个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的语法图时,他们也忘了订单可能会有所不同.或者他们可能故意将其排除在外,因为首先执行分层部分似乎更合乎逻辑.
有几个这样的次要语法变体没有记录.我认为这并不意味着它们不受支持. Oracle可能会后悔允许这么多奇怪的选项,并希望事情至少看起来很简单.例如,HAVING可以在GROUP BY之前出现,许多旧的并行功能仍然有效(但被忽略)等等.(这就是为什么当人们说他们要快速“解析sql”时我总是笑的 – 祝你好运出来了!)
Oracle 8i语法:
Oracle 9i语法: