oracle 將多行合併成一行

2021-09-29 20:16:36 字數 2784 閱讀 5006

使用者id    使用者名稱    角色

001    admin    管理員

002    betty    教師

001    admin    教師

003    cole    學生

可以看到使用者admin有兩個角色-----管理員和教師(也就是使用者和角色是多對多的關係),我們現在的需求是,將這兩個合併在一塊,由兩行資料變成一行資料(也就是在形式上將多對多的關係轉成多對一的關係),如下圖所示:

id    使用者名稱    角色

001    admin    管理員,教師

002    betty    教師

003    cole    學生

如何做到呢?我們可以通過wm_concat函式來達到我們的目的:

select other_colums, wmsys.wm_concat (join_colum) as join_result

from table_name

group by other_colums

--將join_colum替換成待合併的列

--將other_colums替換成剩餘的列

--將table_name替換成表名

例子:1.假如有如下檢視:

其中使用者bbb既是管理員又是老師,查詢語句如下:

select userid,username,phone ,wmsys.wm_concat(rolename) as rolename from test_user group by userid,username,phone;

結果如下:

使用者bbb的rolename的內容如下:

拼接後的型別是clob,當然如果要拼接的內容不大,可以在拼接後使用to_char()轉一下。如果clob的內容是亂碼的話,也可以在拼接前對要拼接的內容使用to_char()轉換一下:

select userid,username,phone ,to_char(wmsys.wm_concat(to_char(rolename))) as rolename from test_user group by userid,username,phone;

結果如下:

2.拼接不僅限於varchar2型別的rolename,對於number型別的phone同樣可以做到:

select userid,username,to_char(wmsys.wm_concat(phone)) as phone ,to_char(wmsys.wm_concat(rolename)) as rolename from test_user group by userid,username;

結果如下:

3.如果分隔符不想要逗號「,」而是分號呢?很簡單,可以使用replace函式替換:

select userid,username,replace(to_char(wmsys.wm_concat(phone)),',',';' )as phone ,to_char(wmsys.wm_concat(rolename)) as rolename from test_user group by userid,username;

結果如下:

4.oracle wm_concat函式的弱點

(1) oracle wm_concat函式並不是萬能的,它要求除了拼接的列不同之外,其它的列必須完全一致。我們現在考慮roleid:

select userid,username,roleid,to_char(wmsys.wm_concat(rolename)) as rolename from test_user group by userid,username,roleid;

結果如下:

我們可以發現並沒達到預期的效果,如果去掉group by中的roleid,則會報錯:「不是group by 表示式」,因為select 的字段必須出現在group by中才行。

所以凡事對於不同的列,要麼不查詢,要麼同樣要進行拼接,例如:

select userid,username,to_char(wmsys.wm_concat(roleid)) as roleid,to_char(wmsys.wm_concat(rolename)) as rolename from test_user group by userid,username;

結果如下:

(2)對於含有clob等大字段型別,oracle wm_concat函式無能為力,原因是lob欄位是不能進行group by的,會報錯:「 ora-00932 :資料型別不一致:應為-,但卻獲得clob」。所以這樣的字段是不能放入左邊的select裡面的,但如果clob欄位的內容不大,在varchar2的範圍內,就可以採取變通的方法,將clob轉成varchar2型別:

select userid,username,to_char(wmsys.wm_concat(rolename)) as rolename,to_char(comments) as st  from test_user group by userid,username,to_char(comments);

結果如下:

小結:網上有許多關於多行轉一行的方法,不過很多是要自己寫儲存過程,函式的,顯得麻煩。使用wm_concat函式,乙個sql語句就可以搞定,方便,快捷。

附:使用oracle wm_concat函式建立含有大量列的檢視

網上有個利用oracle wm_concat函式建立含有大量列的檢視的方法,在此也一併記錄下來。

含有大量列的檢視類似"create or replace view as select 欄位1,...欄位50 from tablename" ,基表有50多個字段,要是靠手工寫太麻煩了,有沒有什麼簡便的方法? 當然有了,看我如果應用wm_concat來讓這個需求變簡單:

oracle多行合併成一行

在mysql有關鍵字group concat提供了類似的功能,在oracle中類似功能關鍵字是wm concat.比如我有如下查詢資料 但是我希望能夠顯示成一行查詢出來,結果圖如下 關鍵sql 形如 select t.sglcheckid,wm concat t.salemodulename fro...

將多行合併成一行(awk sed)

mysql dump的時候,需要忽略檢視以免出現definer與本地不一致從而導致失敗。因此寫了如下指令碼把檢視查詢出來 root bdd3c0ee821f rds autorestore mysql e select concat table schema,table name as tablen...

oracle多行記錄合併成一行。

需要做個報表,把多行記錄,合併成一行。簡單記錄下。注 以下內容為虛構資料,可能會出現不太對的現象,邏輯上是對的。現實中的比這複雜。原始表 部門人數 銷售30 售後20行政8 轉成 銷售8人,售後20人,行政8人。考慮到資料庫版本的問題,目前用的是oracle 11g,12g的時候不再有wmsys.w...