2017-03-03 84 views
0

我需要在Oracle SQL中组合多行,但无法访问LISTAGG或wm_concat(禁用EVALUATE_AGGR)。如何在Oracle SQL中组合多行(有多个限制)

我目前使用一个可怕的黑客,这是否:

max(case when rank("table"."column" BY "table"."column2") = 1 then "table"."column" 
||max(case when rank("table"."column" BY "table"."column2") = 2 then "table"."column" 

如果我这样做10次,然后我可以聚合前十行这大约是我所需要的。

有没有更好的方法来做到这一点?也许使用子查询?

注:我需要这个工作在Oracle OBIEE 11.1.1.9。

感谢任何帮助或提示。

+1

[各种技术显示在这里](https://oracle-base.com/articles/misc/string-aggregation-techniques)。 'sys_connect_by_path'可能是一个开始的地方,因为你已经对它们进行了排名。 –

+0

谢谢。我已经看到这个,但LISTAGG,wm_concat和COLLECT没有启用,我没有权限写自己的函数。 好的:也许我可以让sys_connect_by_path工作 – delica

+0

@delica这是要进入OBIEE的直接数据库请求吗?或者你将尝试将其加入RPD中? –

回答

3

呃。我不喜欢把它写成答案,但我发现Oracle-Base(请参阅Alex Poole的评论)和William Robertson的网站(引用Oracle-Base文章)中的解决方案并不完美,将不适合评论。

Oracle的基本环节:https://oracle-base.com/articles/misc/string-aggregation-techniques#row_number 威廉·罗伯逊网站:http://www.williamrobertson.net/documents/one-row.html

在甲骨文基本的解决方案使用两个调用row_number()只需要一个时,它使用汇总查询,而不是connect_by_isleaf。也许这是William最初发布的解决方案,但他的页面目前有更好的解决方案,只需使用一个row_number()调用和connect_by_isleaf而不是聚合。

但是,在William的页面上,他使用ltrim()而没有显示要修剪哪个字符的参数,所以实际上它没有效果。并且他从row_number()的值中减去1,所以在结果中,每个逗号分隔列表中的第一个标记被省略。

这里是更正的解决方案 - 供参考;我声称对此没有任何独创性。插图在标准SCOTT模式的EMP表中运行。

select deptno 
    , ltrim(sys_connect_by_path(ename,','), ',') as name_list 
from (select deptno 
       , ename 
       , row_number() over (partition by deptno order by ename) as seq 
     from emp) 
where connect_by_isleaf = 1 
connect by seq = prior seq + 1 and deptno = prior deptno 
start with seq = 1; 

DEPTNO NAME_LIST 
------ ------------------------------------ 
10  CLARK,KING,MILLER 
20  ADAMS,FORD,JONES,SCOTT,SMITH 
30  ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD 
+0

好点。现在我检查了一下,我在2004年写道,我不知道'ltrim'或'-1'在那里。 –

+0

@WilliamRobertson - 修复它永远不会太晚!正如你所看到的,人们仍然会回到它(有一个很好的理由:当人们不能使用像LISTAGG这样的更新工具时,这是正确的答案)。 – mathguy

+0

别担心,我会复制你的版本:) –