是否有可能构造SQL来连接列值 多行吗?

举例如下:

表一个

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有什么帮助吗?


当前回答

对于那些必须使用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

其他回答

试试下面的代码:

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

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

将服务器设置为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;

所有值都可以按需要重新排序。各个连接的描述可以在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

还有一个XMLAGG函数,它适用于11.2之前的版本。因为WM_CONCAT没有文档,Oracle也不支持,所以建议不要在生产系统中使用它。

使用XMLAGG你可以做以下事情:

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

它的作用是

将employee_names表中的ename列的值(用逗号连接)放在xml元素中(带有标记E) 提取其中的文本 聚合XML(连接它) 将结果列命名为Result

在想要连接的选择中,调用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

Function Header语法可能是错误的,但原理是正确的。