思路,如果欲将多记录中的某列值合并到一列中,必须使用oracle的树递归方式,即start with id = ? connect by prior id = pid 的方式,并使用SYS_CONNECT_BY_PATH语法。因此第一步需要做的是实现目标表的父子关系,在无需分组合并的情况下,使用伪列ROWNUM生成唯一序号即可;如果需要分组合并较为复杂,因为ROWNUM是唯一顺序号导致无法分组,考虑分析函数ROW_NUMBER()却因为每组中均会出现1,2,3,……,n等数据,导致建立的父子关系重复,此时可采用分析函数lag()来实现父子关系。具体范例见下。
为了方便说明,采用sys用户下的user_tab_cols系统表做为说明范例。在非分组情况下对某一给定的table_name,将column_name合成一个字段并使用“|”作为column_name间的分隔符;在分组情况下按table_name作为分组条件,将每个table_name下的column_name合并到一个字段中,同样使用“|”作为column_name间的分隔符
一、非分组情况下
--非分组
WITH a AS (
SELECT TT.*, SYS_CONNECT_BY_PATH(TT.COLUMN_NAME, '|') path
FROM (SELECT ROWNUM ID, ROWNUM - 1 PID, T.COLUMN_NAME
FROM USER_TAB_COLS T
WHERE T.TABLE_NAME = UPPER('all_objects')) TT
START WITH ID = 1
CONNECT BY PRIOR ID = PID)
SELECT SUBSTR(PATH, 2)
FROM (SELECT ROWNUM RN, AA.*
FROM (SELECT A.* FROM A ORDER BY LENGTH(A.PATH) DESC) AA)
WHERE RN = 1;
二、分组情况下
--分组
WITH a AS
(SELECT T.COLUMN_NAME F1,
T.TABLE_NAME || T.COLUMN_NAME ID,
T.TABLE_NAME PID,
LAG(T.TABLE_NAME || T.COLUMN_NAME, 1, NULL) OVER(PARTITION BY T.TABLE_NAME ORDER BY T.TABLE_NAME) PPID
FROM USER_TAB_COLS T)
SELECT PID TABLE_NAME, SUBSTR(PATH, 2)
FROM (SELECT TTT.*,
ROW_NUMBER() OVER(PARTITION BY PID ORDER BY LENGTH(PATH) DESC) RN
FROM (SELECT A.*, SYS_CONNECT_BY_PATH(A.F1, '|') PATH
FROM A
START WITH PPID IS NULL
CONNECT BY PRIOR ID = PPID) TTT)
WHERE RN = 1;
---END