[英]SQL Query to concatenate column values from multiple rows in Oracle
可以构造SQL来连接多行中的列值吗?
以下是一个示例:
表A
PID A B C
表B
PID SEQ Desc A 1 Have A 2 a nice A 3 day. B 1 Nice Work. C 1 Yes C 2 we can C 3 do C 4 this work!
SQL的输出应为-
PID Desc A Have a nice day. B Nice Work. C Yes we can do this work!
因此,基本上,输出表的Desc列是表B中SEQ值的串联?
对SQL有帮助吗?
还有一个XMLAGG
函数,可用于11.2之前的版本。 由于WM_CONCAT
是Oracle未记录和不支持的 ,因此建议不要在生产系统中使用它。
使用XMLAGG
您可以执行以下操作:
SELECT XMLAGG(XMLELEMENT(E,ename||',')).EXTRACT('//text()') "Result"
FROM employee_names
这是什么
employee_names
表中ename
列的值(用逗号连接)放在xml元素中(带有标签E) 使用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版中引入的,使聚集字符串非常容易。 如果您使用的是11g第2版,则应使用此函数进行字符串聚合。 请参考以下网址,以获取有关字符串连接的更多信息。
http://www.oracle-base.com/articles/misc/StringAggregationTechniques.php
正如大多数答案所暗示的那样, LISTAGG
是显而易见的选择。 但是, LISTAGG
一个令人讨厌的方面是,如果串联字符串的总长度超过4000个字符(SQL中的VARCHAR2
限制),则会引发以下错误,这在Oracle 12.1版之前的版本中很难管理。
ORA-01489:字符串连接的结果太长
LISTAGG
的ON OVERFLOW
子句是12cR2中添加的新功能。 包含此子句的查询如下所示:
SELECT pid, LISTAGG(Desc, ' ' on overflow truncate) WITHIN GROUP (ORDER BY seq) AS desc
FROM B GROUP BY pid;
以上将输出限制为4000个字符,但不会引发ORA-01489
错误。
这些是ON OVERFLOW
子句的一些附加选项:
ON OVERFLOW TRUNCATE 'Contd..'
:这将在字符串的末尾显示'Contd..'
(默认为...
) ON OVERFLOW TRUNCATE ''
:将显示4000个字符而没有任何终止字符串。 ON OVERFLOW TRUNCATE WITH COUNT
:将在结束字符之后的末尾显示字符总数。 例如: ...(5512)
' ON OVERFLOW ERROR
:如果您期望LISTAGG
失败并出现ORA-01489
错误(无论如何都是默认值)。 对于必须使用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;
所有值都可以根据需要重新排序。 各个串联的描述可以在PARTITION BY子句中重新排序,而PID列表可以在最终的ORDER BY子句中重新排序。
或者:有时您可能希望将整个表中的所有值连接成一行。
这里的关键思想是为要连接的一组描述使用人工值。
在以下查询中,使用常量字符串“ 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子句中重新排序。
此页面上的其他几个答案也提到了此非常有用的参考: https : //oracle-base.com/articles/misc/string-aggregation-techniques
如果必须进行排序,LISTAGG可提供最佳性能(00:00:05.85)
SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description FROM B GROUP BY pid;
如果不需要排序,COLLECT可以提供最佳性能(00:00:02.90):
SELECT pid, TO_STRING(CAST(COLLECT(Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;
按顺序进行收藏会比较慢(00:00:07.08):
SELECT pid, TO_STRING(CAST(COLLECT(Desc ORDER BY Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;
所有其他技术都比较慢。
在运行选择查询之前,请运行以下命令:
SET SERVEROUT ON SIZE 6000
SELECT XMLAGG(XMLELEMENT(E,SUPLR_SUPLR_ID||',')).EXTRACT('//text()') "SUPPLIER"
FROM SUPPLIERS;
我使用LISTAGG,但是将此字符串返回波斯字符串!
我的查询:
SELECT
listagg(DESCRIPTION,' , ') within group (order by DESCRIPTION)
FROM
B_CEREMONY
结果:
'A7'1 , ,4F
请帮我。
哇,这个解决方案是可行的:
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';
在选择要串联的位置,调用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
函数头语法可能是错误的,但是该原理确实有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.