<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Decode360's Blog

    業精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 ::  :: 管理 ::
      397 隨筆 :: 33 文章 :: 29 評論 :: 0 Trackbacks
    SQL行列轉換
    ?
    ?
    ??? 在數據庫開發的過程中,行列轉換是一個一定會遇到的問題,解決的方法也有很多,但是對于一些需求復雜,非常制式化的report需求,行列轉換真的是要做到頭大,需要進行模塊化的PLSQL編程來解決。本文摘錄了在Oracle環境下,解決單個字符的行列轉換問題的幾種常用方法,具體如下:
    ?
    ??? 首先模擬一下環境,現有的表結構是:
    ?
    create table t8 (i int ,a number ,b varchar2 ( 20 ));
    insert into?? t8 values ( 1 , 2 , 'c' );
    insert into?? t8 values ( 1 , 3 , 'x' );
    insert into?? t8 values ( 1 , 4 , 'b' );
    insert into?? t8 values ( 2 , 5 , 'd' );
    insert into?? t8 values ( 2 , 6 , 'h' );
    insert into?? t8 values ( 3 , 7 , 'j' );
    insert into?? t8 values ( 3 , 8 , 'y' );
    insert into?? t8 values ( 3 , 9 , 'l' );
    insert into?? t8 values ( 3 , 10 , 'v' );
    commit;
    ?
    SQL> select * from t8;
    ?
    ???????? I????????? A B
    ---------- ---------- ----------
    ???????? 1????????? 2 c
    ???????? 1????????? 3 x
    ???????? 1????????? 4 b
    ???????? 2????????? 5 d
    ???????? 2????????? 6 h
    ???????? 3????????? 7 j
    ???????? 3????????? 8 y
    ???????? 3????????? 9 l
    ???????? 3???????? 10 v
    ?
    已選擇 9 行。
    ?
    ?
    ??? 希望得到的結果是這樣的:
    ?
    I?????? CHAR
    ------- ----------
    1?????? c,x,b
    2?????? d,h
    3?????? j,y,l,v
    ?
    ?
    方法一:
    ?
    ??? 如果是 10g ,則可使用最簡單的方法:wm_sys.wm_concat函數 (wm_sys不加也可)
    ?
    SQL> select i,wmsys.wm_concat(b) from t8 group by i;
    ?
    ???????? I WMSYS.WM_CONCAT(B)
    ---------- --------------------
    ???????? 1 c,x,b
    ???????? 2 d,h
    ???????? 3 j,y,l,v
    ?
    ??? 缺點:不能加排序功能,例如按 a 列逆序排列,需要在前一層排好序之后再使用wmsys.wm_concat
    ?
    ?
    方法二:
    ?
    ??? 9i 及 9i 以前的數據庫版本可使用 connect by 來實現子葉的連接:
    ?
    select i, ltrim(max (sys_connect_by_path(b, ',' )), ',' ) b
    ? from (select i, b, a,
    ?????????????? min (a) over( partition by i) a_min,
    ?????????????? (row_number() over( order by i, a)) +
    ?????????????? (dense_rank() over( order by i)) numid
    ????????? from t8)
    ? start with a = a_min
    connect by numid - 1 = prior numid
    ? group by i;
    ?
    解釋一下這段 SQL :
    ?
    1、最里面一層,對表 t8 進行處理,主要是列出了列 numid 用于等下的 connect by 操作,具體效果如下:
    ?
    SQL> select i,b,a,min(a) over(partition by i) a_min,
    ? 2? (row_number() over(order by i, a)) a,
    ? 3? (dense_rank() over(order by i)) b,
    ? 4? (row_number() over(order by i, a)) +(dense_rank() over(order by i)) numid
    ? 5? from t8;
    ?
    ?? I B?????? A????? A_MIN??? A??? B????? NUMID
    ---- ---- ---- ---------- ---- ---- ----------
    ?? 1 c?????? 2????????? 2??? 1??? 1????????? 2
    ?? 1 x?????? 3????????? 2??? 2??? 1????????? 3
    ?? 1 b?????? 4????????? 2??? 3??? 1????????? 4
    ?? 2 d?????? 5????????? 5??? 4??? 2????????? 6
    ?? 2 h?????? 6????????? 5??? 5??? 2????????? 7
    ?? 3 j?????? 7????????? 7??? 6??? 3????????? 9
    ?? 3 y?????? 8????????? 7??? 7??? 3???????? 10
    ?? 3 l?????? 9????????? 7??? 8??? 3???????? 11
    ?? 3 v????? 10????????? 7??? 9??? 3???????? 12
    ?
    9 rows selected
    ?
    其中 row_mun 產生依次列表, dense_rank 產生相同值相同排名,這樣通過 dense_rank 就可以區分出在哪里截斷 connect by
    從 numid 列可以看出,每個相同的 i 對應一組序列,之后跳過一個數字后繼續形成序列
    ?
    2、通過 sys_connect_by_path ,以及 start with a = a_min connect by numid - 1 = prior numid 來形成一個分支列表,結果如下:
    ?
    ?? I B
    ---- --------
    ?? 1 ,c
    ?? 1 ,c,x
    ?? 1 ,c,x,b
    ?? 2 ,d
    ?? 2 ,d,h
    ?? 3 ,j
    ?? 3 ,j,y
    ?? 3 ,j,y,l
    ?? 3 ,j,y,l,v
    ?
    3、通過 max 函數選出我們需要的每個 i 對應的最后一列
    ?
    ?? I B
    ---- --------
    ?? 1 ,c,x,b
    ?? 2 ,d,h
    ?? 3 ,j,y,l,v
    ?
    4、用 ltrim 或 substr 來去掉最前面的 “,”
    ?
    ?
    方法三:
    ?
    自己寫一個函數來處理:
    ?
    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 b from t8 where i=' || n || ' order by a' ;
    ? 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 t8 group by i;
    ?
    ?? I MY_CONCAT(I)
    ---- ----------------------
    ?? 1 c,x,b
    ?? 2 d,h
    ?? 3 j,y,l,v
    ?
    ?
    ?
    posted on 2008-09-08 19:31 decode360 閱讀(615) 評論(0)  編輯  收藏 所屬分類: 05.SQL
    主站蜘蛛池模板: 亚洲日产乱码一二三区别 | 亚洲一区二区三区在线观看精品中文 | 亚洲视频国产精品| 免费观看91视频| 无码欧精品亚洲日韩一区| 91免费国产视频| 亚洲AV无码久久精品成人 | 亚洲偷自拍另类图片二区| 无码国产精品久久一区免费| 国产91在线|亚洲| 永久免费av无码网站大全| 日本高清不卡中文字幕免费| 亚洲性日韩精品国产一区二区| 久久精品免费大片国产大片| 亚洲国产精品一区二区成人片国内 | 最新国产AV无码专区亚洲| a色毛片免费视频| 日韩精品亚洲人成在线观看| 亚洲免费在线观看视频| 亚洲中文无码亚洲人成影院| 国产一级理论免费版| 亚洲天堂免费在线视频| 亚洲国产一区在线| aa级一级天堂片免费观看| 亚洲AV女人18毛片水真多| 亚洲色一色噜一噜噜噜| 四虎影视成人永久免费观看视频 | 一级毛片无遮挡免费全部| 亚洲av永久无码精品漫画| 一个人免费观看在线视频www| 亚洲av永久无码精品秋霞电影秋| 亚洲精品国自产拍在线观看| 无码人妻AV免费一区二区三区 | 免费国产高清毛不卡片基地| 亚洲国产AV无码专区亚洲AV| 三年片在线观看免费观看高清电影| 爱情岛亚洲论坛在线观看| 亚洲精品美女久久777777| 无码国产精品一区二区免费式影视 | 久久久久久国产a免费观看黄色大片| 国产成人精品日本亚洲语音|