表結(jié)構(gòu)和數(shù)據(jù)如下(表名Test):
NO VALUE NAME
1 a 測試1
1 b 測試2
1 c 測試3
1 d 測試4
2 e 測試5
4 f 測試6
4 g 測試7
Sql語句:
select No,
ltrim(max(sys_connect_by_path(Value, ';')), ';') as Value,
ltrim(max(sys_connect_by_path(Name, ';')), ';') as Name
from (select No,
Value,
Name,
rnFirst,
lead(rnFirst) over(partition by No order by rnFirst) rnNext
from (select a.No,
a.Value,
a.Name,
row_number() over(order by a.No, a.Value desc) rnFirst
from Test a) tmpTable1) tmpTable2
start with rnNext is null
connect by rnNext = PRior rnFirst
group by No;
檢索結(jié)果如下:
NO VALUE NAME
1 a;b;c;d 測試1;測試2;測試3;測試4
2 e 測試5
4 f;g 測試6;測試7
簡單解釋一下那個(gè)Sql吧:
1、最內(nèi)層的Sql(即表tmpTable1),按No和Value排序,并列出行號:
select a.No,
a.Value,
a.Name,
row_number() over(order by a.No, a.Value desc) rnFirst
from Test a
該語句結(jié)果如下:
NO VALUE NAME RNFIRST
1 d 測試4 1
1 c 測試3 2
1 b 測試2 3
1 a 測試1 4
2 e 測試5 5
4 g 測試7 6
4 f 測試6 7
2、外層的Sql(即表tmpTable2),根據(jù)No分區(qū),取出當(dāng)前行對應(yīng)的下一條記錄的行號字段:
select No,
Value,
Name,
rnFirst,
lead(rnFirst) over(partition by No order by rnFirst) rnNext
from (這里是tmpTable1的SQL) tmpTable1
lead(rnFirst):取得下一行記錄的rnFirst字段
over(partition by No order by rnFirst) 按rnFirst排序,并按No分區(qū),分區(qū)就是如果下一行的No字段與當(dāng)前行的No字段不相等時(shí),不取下一行記錄顯示
該語句結(jié)果如下:
NO VALUE NAME RNFIRST RNNEXT
1 d 測試4 1 2
1 c 測試3 2 3
1 b 測試2 3 4
1 a 測試1 4 NULL
2 e 測試5 5 NULL
4 g 測試7 6 7
4 f 測試6 7 NULL
3、最后就是最外層的sys_connect_by_path函數(shù)與start遞歸了
sys_connect_by_path(Value, ';')
start with rnNext is null
connect by rnNext = prior rnFirst
這個(gè)大概意思就是從rnNext為null的那條記錄開始,遞歸查找,
如果前一記錄的rnFirst字段等于當(dāng)前記錄的rnNext字段,就把2條記錄的Value用分號連接起來,
大家可以先試試下面這個(gè)沒有Max和Group的Sql:
select No,
sys_connect_by_path(Value, ';') as Value,
sys_connect_by_path(Name, ';') as Name
from (select No,
Value,
Name,
rnFirst,
lead(rnFirst) over(partition by No order by rnFirst) rnNext
from (select a.No,
a.Value,
a.Name,
row_number() over(order by a.No, a.Value desc) rnFirst
from Test a) tmpTable1) tmpTable2
start with rnNext is null
connect by rnNext = prior rnFirst
結(jié)果是:
NO VALUE NAME
1 ;a ;測試1
1 ;a;b ;測試1;測試2
1 ;a;b;c ;測試1;測試2;測試3
1 ;a;b;c;d ;測試1;測試2;測試3;測試4
2 ;e ;測試5
4 ;f ;測試6
4 ;f;g ;測試6;測試7
可以看到,每個(gè)No的最后一條記錄就是我們要的了
所以在sys_connect_by_path外面套一個(gè)Max,再加個(gè)Group by No,得到的結(jié)果就是行轉(zhuǎn)列的結(jié)果了
最后再加一個(gè)Ltrim,去掉最前面的那個(gè)分號,完成。