若是是oracle 10g以上 一個wm_concat函數就能夠解決。數據庫
若是是oracle 9i如下就有點麻煩了。oracle
表結構以下:函數
NAME Null Type學習
N_SEC_CODE NOT NULL CHAR(6)測試
C_RESEARCHER_CODE NOT NULL VARCHAR2(20)google
此表保存了「股票」與「研究員」的對應關係數據,通常而言,對於同一只股票而言,可能有多個研究員code
對其進行跟蹤研究。因此目前遇到一個要求,需查詢出每隻股票和對應的研究員(研究員代碼間,使用逗號分隔)。it
例若有以下數據:io
000297 chenpengtable
000297 liusu
合併處理後需顯示爲:
000297 chenpeng,liusu
網上查了不少方法,但一般而言都是編寫自定義多行文本合併函數,或者對支持的列數具備侷限性。
最後在英文google中搜到以下比較巧的方法。不用在數據庫中增長function,純SQL一次性搞定,
並且擴充性很好,沒有列的限制。
ORACLE純SQL實現多行合併一行 - 南鄉子 - 旅夜書懷ORACLE純SQL實現多行合併一行 - 南鄉子 - 旅夜書懷Code
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分析:
一、利用 「ROW_NUMBER () OVER (PARTITION BY……」 爲按「股票代碼」彙總後的數據行添加組內序號
二、「SYS_CONNECT_BY_PATH」 按組內序號相鄰關係,爲每一層進行不一樣行的「研究員代碼」疊加
三、再次利用「股票代碼」進行組內分組,但按第二部中的層次排倒序,增長調整後等級
四、取全部調整後等級爲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
又一個示例: WITH tab AS( select '01' no,'ss' name, 10 jiner,'麥子' you from dual union all select '02' no,'dd' name, 11 jiner,'蘿蔔' you from dual union all select '03' no,'cc' name, 9 jiner,'大豆' you from dual union all select '01' no,'ss' name, 10 jiner,'白菜' you from dual) SELECT a.no, a.name, a.jiner, ltrim(MAX(sys_connect_by_path(you, ',')), ',') you FROM (SELECT row_number() over(PARTITION BY a.no, a.name, a.jiner ORDER BY a.no, a.name, a.jiner) rn,a.* FROM tab a) a START WITH rn = 1 CONNECT BY PRIOR rn = rn - 1 AND a.no = PRIOR a.no AND a.name = PRIOR a.name AND a.jiner = PRIOR a.jiner GROUP BY a.no, a.name, a.jiner
oracle wm_concat函數,用於列轉行,逗號分隔
首先讓咱們來看看這個神奇的函數wm_concat(列名),該函數能夠把列值以","號分隔起來,並顯示成一行,接下來上例子,看看這個神奇的函數如何應用 準備測試數據 SQL> create table test(id number,name varchar2(20));
SQL> insert into test values(1,'a');
SQL> insert into test values(1,'b');
SQL> insert into test values(1,'c');
SQL> insert into test values(2,'d');
SQL> insert into test values(2,'e');
SQL> commit;
效果1 : 行轉列 SQL> select wm_concat(name) from test;
WM_CONCAT(NAME)
a,b,c,d,e
效果2: 把結果裏的逗號替換成"|" SQL> select replace(wm_concat(name),',','|') from test;
REPLACE(WM_CONCAT(NAME),',','|')
a|b|c|d|e
效果3:按ID分組合並name
SQL> select id,wm_concat(name) name from test group by id;
ID NAME
1 a,b,c
2 d,e
懶人擴展用法:
案例:我要寫一個視圖,相似"create or replace view as select 字段1,...字段50 from tablename" ,基表有50多個字段,要是靠手工寫太麻煩了,有沒有什麼簡便的方法? 固然有了,看我若是應用wm_concat來讓這個需求變簡單
SQL> select 'create or replace view as select '|| wm_concat(column_name) || ' from dept'from user_tab_columns where table_name='DEPT';
'CREATEORREPLACEVIEWASSELECT'||WM_CONCAT(COLUMN_NAME)||'FROMDEPT'
create or replace view as select DEPTNO,DNAME,LOC from dept