国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > Oracle > 正文

Oracle中,用一條Sql實現任意的行轉列拼接 多行拼接

2024-08-29 13:53:39
字體:
來源:轉載
供稿:網友
表結構和數據如下(表名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;



檢索結果如下:

NO VALUE    NAME
1    a;b;c;d   測試1;測試2;測試3;測試4
2    e            測試5
4    f;g          測試6;測試7

簡單解釋一下那個Sql吧:
1、最內層的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
該語句結果如下:
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),根據No分區,取出當前行對應的下一條記錄的行號字段:
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分區,分區就是如果下一行的No字段與當前行的No字段不相等時,不取下一行記錄顯示
該語句結果如下:
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函數與start遞歸了
sys_connect_by_path(Value, ';')
start with rnNext is null
connect by rnNext = prior rnFirst
這個大概意思就是從rnNext為null的那條記錄開始,遞歸查找,
如果前一記錄的rnFirst字段等于當前記錄的rnNext字段,就把2條記錄的Value用分號連接起來,
大家可以先試試下面這個沒有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

結果是:
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

可以看到,每個No的最后一條記錄就是我們要的了
所以在sys_connect_by_path外面套一個Max,再加個Group by No,得到的結果就是行轉列的結果了
最后再加一個Ltrim,去掉最前面的那個分號,完成。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 甘孜县| 大城县| 泽普县| 门源| 雷波县| 五大连池市| 莱阳市| 绥宁县| 聂拉木县| 菏泽市| 剑川县| 石泉县| 涪陵区| 海晏县| 延川县| 临沭县| 黑河市| 岑巩县| 大渡口区| 龙南县| 年辖:市辖区| 镇平县| 长治县| 阿巴嘎旗| 枣阳市| 马鞍山市| 吐鲁番市| 高密市| 巫山县| 台山市| 卓尼县| 房山区| 温泉县| 安塞县| 贵港市| 商河县| 娄底市| 武鸣县| 湘阴县| 珠海市| 来安县|