日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Oracle 多行合并一行 方法

發布時間:2024/4/17 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle 多行合并一行 方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?http://lovejuan1314.iteye.com/blog/413694

NOTE:特別聲明一下內容轉自網絡
http://www.ningoo.net/html/2008/how_to_do_string_aggregate_on_oracle.html

假如有如下表,其中各個i值對應的行數是不定的

Sql代碼 ?
  • SQL>?select?*?from?t; ??
  • ??
  • ?????????I?A??????????D ??
  • ----------?----------?------------------- ??
  • ?????????1?b??????????2008-03-27?10:55:42 ??
  • ?????????1?a??????????2008-03-27?10:55:46 ??
  • ?????????1?d??????????2008-03-27?10:55:30 ??
  • ?????????2?z??????????2008-03-27?10:55:55 ??
  • ?????????2?t??????????2008-03-27?10:55:59 ??
  • ??
  • ---?要獲得如下結果,注意字符串需要按照D列的時間排序: ??
  • ??
  • 1??d,b,a ??
  • 2??z,t??
  • SQL> select * from t;I A D ---------- ---------- -------------------1 b 2008-03-27 10:55:421 a 2008-03-27 10:55:461 d 2008-03-27 10:55:302 z 2008-03-27 10:55:552 t 2008-03-27 10:55:59--- 要獲得如下結果,注意字符串需要按照D列的時間排序:1 d,b,a 2 z,t



    這是一個比較典型的行列轉換,有好幾種實現方法

    1.自定義函數實現

    Sql代碼 ?
  • create?or?replace?function?my_concat(n?number) ??
  • return?varchar2 ??
  • is??
  • ?type?typ_cursor?is?ref?cursor; ??
  • ?v_cursor?typ_cursor; ??
  • ?v_temp?varchar2(10); ??
  • ?v_result?varchar2(4000):=?''; ??
  • ?v_sql?varchar2(200); ??
  • begin??
  • ?v_sql?:=?'select?a?from?t?where?i='?||?n?||'?order?by?d'; ??
  • ?open?v_cursor?for?v_sql; ??
  • ?loop ??
  • ????fetch?v_cursor?into?v_temp; ??
  • ????exit?when?v_cursor%notfound; ??
  • ????v_result?:=?v_result?||','?||?v_temp; ??
  • ?end?loop; ??
  • ?return?substr(v_result,2); ??
  • end; ??
  • ??
  • SQL>?select?i,my_concat(i)?from?t?group?by?i; ??
  • ??
  • ?????????I?MY_CONCAT(I) ??
  • ----------?-------------------- ??
  • ?????????1?d,b,a ??
  • ?????????2?z,t??
  • create or replace function my_concat(n number) return varchar2 istype typ_cursor is ref cursor;v_cursor typ_cursor;v_temp varchar2(10);v_result varchar2(4000):= '';v_sql varchar2(200); beginv_sql := 'select a from t where i=' || n ||' order by d';open v_cursor for v_sql;loopfetch v_cursor into v_temp;exit when v_cursor%notfound;v_result := v_result ||',' || v_temp;end loop;return substr(v_result,2); end;SQL> select i,my_concat(i) from t group by i;I MY_CONCAT(I) ---------- --------------------1 d,b,a2 z,t



    雖然這種方式可以實現需求,但是如果表t的數據量很大,i的值又很多的情況下,因為針對每個i值都要執行一句select,掃描和排序的次數和i的值成正比,性能會非常差。

    2.使用sys_connect_by_path

    Sql代碼 ?
  • select?i,ltrim(max(sys_connect_by_path(a,',')),',')?a ??
  • from??
  • ( ??
  • select?i,a,d,min(d)?over(partition?by?i)?d_min, ??
  • (row_number()?over(order?by?i,d))+(dense_rank()?over?(order?by?i))?numid ??
  • from?t ??
  • ) ??
  • start?with?d=d_min?connect?by?numid-1=prior?numid ??
  • group?by?i;??
  • select i,ltrim(max(sys_connect_by_path(a,',')),',') a from ( select i,a,d,min(d) over(partition by i) d_min, (row_number() over(order by i,d))+(dense_rank() over (order by i)) numid from t ) start with d=d_min connect by numid-1=prior numid group by i;


    從執行計劃上來看,這種方式只需要掃描兩次表,比自定義函數的方法,效率要高很多,尤其是表中數據量較大的時候:

    3.使用wm_sys.wm_concat
    這個函數也可以實現類似的行列轉換需求,但是似乎沒有辦法做到直接根據另外一列排序,所以需要先通過子查詢或者臨時表排好序:

    Sql代碼 ?
  • SQL>?select?i,wmsys.wm_concat(a)?from?t?group?by?i; ??
  • ??
  • ?????????I?WMSYS.WM_CONCAT(A) ??
  • ----------?-------------------- ??
  • ?????????1?b,a,d ??
  • ?????????2?z,t ??
  • ??
  • SQL>?select?i,wmsys.wm_concat(a) ??
  • ??2??from??
  • ??3??(select?*?from?t?order?by?i,d) ??
  • ??4??group?by?i; ??
  • ??
  • ?????????I?WMSYS.WM_CONCAT(A) ??
  • ----------?-------------------- ??
  • ?????????1?d,b,a ??
  • ?????????2?z,t??
  • SQL> select i,wmsys.wm_concat(a) from t group by i;I WMSYS.WM_CONCAT(A) ---------- --------------------1 b,a,d2 z,tSQL> select i,wmsys.wm_concat(a)2 from3 (select * from t order by i,d)4 group by i;I WMSYS.WM_CONCAT(A) ---------- --------------------1 d,b,a2 z,t


    執行計劃上看,只需要做一次表掃描就可以了,但是這個函數是加密過的,執行計劃并不能顯示函數內部的操作。


    其他一些方法:
    http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2196162600402
    http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:15637744429336

    總結

    以上是生活随笔為你收集整理的Oracle 多行合并一行 方法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。