SQL Query连接Oracle中多行的列值

是否有可能构buildSQL来连接来自多行的列值?

以下是一个例子:

表A

 PID
一个
乙
 C

表B

 PID SEQ

 A 1有
 2一个不错的
 3天。
 B 1很好的工作。
 C 1是的
 C 2我们可以 
 C 3做 
 C 4这个工作!

SQL的输出应该是 –

 PID说明
一个愉快的一天。
 B很好的工作。
 C是的,我们可以做这个工作!

那么基本上输出表的Desc列是来自表B的SEQ值的串联?

任何帮助与SQL?

有几种方法取决于你有什么版本 – 请参阅关于string聚合技术的oracle文档 。 一个很常见的是使用LISTAGG

 SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS desc FROM B GROUP BY pid; 

然后join到A挑选你想要的pids

注意:开箱即用, LISTAGG只能与VARCHAR2列正常工作。

还有一个XMLAGG函数,它可以在11.2之前的版本上运行。 由于WM_CONCAT 没有logging,Oracle不支持 ,因此build议不要在生产系统中使用它。

使用XMLAGG您可以执行以下操作:

 SELECT XMLAGG(XMLELEMENT(E,ename||',')).EXTRACT('//text()') "Result" FROM employee_names 

这是做什么的

  • employee_names表中ename列的值(用逗号连接)放在一个xml元素中(带有标记E)
  • 提取这个文本
  • 聚合XML(连接它)
  • 调用结果列“结果”

用SQL模型子句:

 SQL> select pid 2 , ltrim(sentence) sentence 3 from ( select pid 4 , seq 5 , sentence 6 from b 7 model 8 partition by (pid) 9 dimension by (seq) 10 measures (descr,cast(null as varchar2(100)) as sentence) 11 ( sentence[any] order by seq desc 12 = descr[cv()] || ' ' || sentence[cv()+1] 13 ) 14 ) 15 where seq = 1 16 / P SENTENCE - --------------------------------------------------------------------------- A Have a nice day B Nice Work. C Yes we can do this work! 3 rows selected. 

我在这里写了这个。 如果您按照OTN线程的链接,您会发现更多,包括性能对比。

问候,
抢。

LISTAGG分析函数在Oracle 11g第2版中引入,使得聚合string变得非常容易。 如果您使用11g第2版,则应该使用此函数进行string聚合。 有关string连接的更多信息,请参阅下面的url。

http://www.oracle-base.com/articles/misc/StringAggregationTechniques.php

string连接

在运行select查询之前,运行以下命令:

SET SERVEROUT ON SIZE 6000

 SELECT XMLAGG(XMLELEMENT(E,SUPLR_SUPLR_ID||',')).EXTRACT('//text()') "SUPPLIER" FROM SUPPLIERS; 

对于那些必须使用Oracle 9i(或更早版本)来解决这个问题的人来说,可能需要使用SYS_CONNECT_BY_PATH,因为LISTAGG不可用。

要回答OP,以下查询将显示来自表A的PID,并连接来自表B的所有DESC列:

 SELECT pid, SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions FROM ( SELECT ROW_NUMBER () OVER (PARTITION BY pid ORDER BY pid, seq) rnum, pid, description FROM ( SELECT a.pid, seq, description FROM table_a a, table_b b WHERE a.pid = b.pid(+) ) ) START WITH rnum = 1 CONNECT BY PRIOR rnum = rnum - 1 AND PRIOR pid = pid GROUP BY pid ORDER BY pid; 

也可能有键和值都包含在一个表中的情况。 在没有表A的情况下可以使用以下查询,并且只有表B存在:

 SELECT pid, SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions FROM ( SELECT ROW_NUMBER () OVER (PARTITION BY pid ORDER BY pid, seq) rnum, pid, description FROM ( SELECT pid, seq, description FROM table_b ) ) START WITH rnum = 1 CONNECT BY PRIOR rnum = rnum - 1 AND PRIOR pid = pid GROUP BY pid ORDER BY pid; 

所有的值可以根据需要重新sorting。 单独的连接描述可以在PARTITION BY子句中重新sorting,PID的列表可以在最后的ORDER BY子句中重新sorting。


或者:有时您可能需要将整个表中的所有值连接成一行。

这里的关键思想是使用人工值来描述一组描述。

在下面的查询中,使用常量string“1”,但是任何值都可以使用:

 SELECT SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions FROM ( SELECT ROW_NUMBER () OVER (PARTITION BY unique_id ORDER BY pid, seq) rnum, description FROM ( SELECT '1' unique_id, b.pid, b.seq, b.description FROM table_b b ) ) START WITH rnum = 1 CONNECT BY PRIOR rnum = rnum - 1; 

单独的连接描述可以在PARTITION BY子句中重新sorting。

此页面上的其他几个答案也提到了这个非常有用的参考: https : //oracle-base.com/articles/misc/string-aggregation-techniques

LISTAGG的使用是最实用的,它提供了最好的性能,除了一个例外,当不需要订购。 更多细节在这里: http : //www.oracle-developer.net/display.php?id=515

我使用LISTAGG,但返回这个string波斯string!

我的查询:

 SELECT listagg(DESCRIPTION,' , ') within group (order by DESCRIPTION) FROM B_CEREMONY 

结果:

 'A7'1 , ,4F 

请帮帮我。

哇这个解决scheme工作:

 SELECT listagg(convert(DESCRIPTION, 'UTF8', 'AL16UTF16'),' , ') within group (order by DESCRIPTION) FROM B_CEREMONY; 

试试这个代码:

  SELECT XMLAGG(XMLELEMENT(E,fieldname||',')).EXTRACT('//text()') "FieldNames" FROM FIELD_MASTER WHERE FIELD_ID > 10 AND FIELD_AREA != 'NEBRASKA'; 

在select你想要连接的地方,调用一个SQL函数。

例如:

 select PID, dbo.MyConcat(PID) from TableA; 

那么对于SQL函数:

 Function MyConcat(@PID varchar(10)) returns varchar(1000) as begin declare @x varchar(1000); select @x = isnull(@x +',', @x, @x +',') + Desc from TableB where PID = @PID; return @x; end 

函数头文件的语法可能是错误的,但是原理确实起作用。

或者是Oracle STRAGG(列)函数。

我不得不说,这种处理非常有限…如果你超过了字段宽度或显示宽度…