1. 程式人生 > >ORACLE純SQL實現多行合併一行

ORACLE純SQL實現多行合併一行

專案中遇到一個需求,需要將多行合併為一行。
表結構如下:
NAME                            Null           Type
------------------------   ---------   -----
N_SEC_CODE                 NOT NULL  CHAR(6)
C_RESEARCHER_CODE   NOT NULL  VARCHAR2(20)

此表儲存了“股票”與“研究員”的對應關係資料,一般而言,對於同一只股票而言,可能有多個研究員
對其進行跟蹤研究。所以目前遇到一個要求,需查詢出每隻股票和對應的研究員(研究員程式碼間,使用逗號分隔)。
例如有如下資料:
000297                                    chenpeng           
000297                                    liusu              
合併處理後需顯示為:
000297                                    chenpeng,liusu

網上查了很多方法,但通常而言都是編寫自定義多行文字合併函式,或者對支援的列數具有侷限性。
最後在英文google中搜到如下比較巧的方法。不用在資料庫中增加function,純SQL一次性搞定,
而且擴充性很好,沒有列的限制。

SELECT   n_sec_code, TRANSLATE (LTRIM (text, '/'), '*/', '*,') researcherList
    FROM (SELECT ROW_NUMBER () OVER (PARTITION BY n_sec_code ORDER BY n_sec_code,
                  lvl DESC) rn,
                 n_sec_code, text
            FROM (SELECT     n_sec_code, LEVEL lvl,
                             SYS_CONNECT_BY_PATH (c_researcher_code,'/') text
                        FROM (SELECT   n_sec_code, c_researcher_code as c_researcher_code,
                                       ROW_NUMBER () OVER (PARTITION BY n_sec_code ORDER BY n_sec_code,c_researcher_code) x
                                  FROM m_researcher_stock_rel
                              ORDER BY n_sec_code, c_researcher_code) a
                  CONNECT BY n_sec_code = PRIOR n_sec_code AND x - 1 = PRIOR x))
   WHERE rn = 1
ORDER BY n_sec_code;


預想的結果成功出現,多行資料成功彙總到一行,特此分享與大家。對於你自己的應用中,只需要把SQL中“n_sec_code”
換為你的用來彙總的列,“c_researcher_code”替換為需合併文字的列,“m_researcher_stock_rel”替換為你的表名,就是這麼簡單。

SQL分析:
1、利用 “ROW_NUMBER () OVER (PARTITION BY……” 為按“股票程式碼”彙總後的資料行新增組內序號
2、“SYS_CONNECT_BY_PATH”  按組內序號相鄰關係,為每一層進行不同行的“研究員程式碼”疊加
3、再次利用“股票程式碼”進行組內分組,但按第二部中的層次排倒序,增加調整後等級
4、取所有調整後等級為1的結果,即為所要求的資料行

方法很巧妙,值得學習。:-)

感謝網友@OctoberOne、@ericqliu的指點,在ORACLE10中可使用以下方法:

SELECT n_sec_code, wmsys.wm_concat (c_researcher_code) as result
FROM m_researcher_stock_rel
GROUP BY n_sec_code