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