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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Oracle 多行记录合并/连接/聚合字符串的几种方法

發布時間:2025/3/20 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle 多行记录合并/连接/聚合字符串的几种方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

怎么合并多行記錄的字符串,一直是oracle新手喜歡問的SQL問題之一,關于這個問題的帖子我看過不下30個了,現在就對這個問題,進行一個總結。
-
什么是合并多行字符串(連接字符串)呢,例如:

1 SQL> desc test; 2 Name Type Nullable Default Comments 3 ------- ------------ -------- ------- -------- 4 COUNTRY VARCHAR2(20) Y 5 CITY VARCHAR2(20) Y 6 7 SQL> select * from test; 8 9 10 COUNTRY CITY 11 -------------------- -------------------- 12 中國 臺北 13 中國 香港 14 中國 上海 15 日本 東京 16 日本 大阪

?

要求得到如下結果集:

1 ------- -------------------- 2 中國 臺北,香港,上海 3 日本 東京,大阪

?


實際就是對字符實現一個聚合功能,我很奇怪為什么Oracle沒有提供官方的聚合函數來實現它呢:)
下面就對幾種經常提及的解決方案進行分析(有一個評測標準最高★★★★★):
1.被集合字段范圍小且固定型 靈活性★ 性能★★★★ 難度 ★
這種方法的原理在于你已經知道CITY字段的值有幾種,且還不算太多,如果太多這個SQL就會相當的長。。看例子:

1 SQL> select t.country, 2 2 MAX(decode(t.city,'臺北',t.city||',',NULL)) || 3 3 MAX(decode(t.city,'香港',t.city||',',NULL))|| 4 4 MAX(decode(t.city,'上海',t.city||',',NULL))|| 5 5 MAX(decode(t.city,'東京',t.city||',',NULL))|| 6 6 MAX(decode(t.city,'大阪',t.city||',',NULL)) 7 7 from test t GROUP BY t.country 8 8 / 9 10 11 COUNTRY MAX(DECODE(T.CITY,'臺北',T.CIT 12 -------------------- ------------------------------ 13 中國 臺北,香港,上海, 14 日本 東京,大阪,

?


大家一看,估計就明白了(如果不明白,好好補習MAX DECODE和分組)。這種方法無愧為最笨的方法,但是對某些應用來說,最有效的方法也許就是它。
2.固定表固定字段函數法 靈活性★★ 性能★★★★ 難度 ★★
此法必須預先知道是哪個表,也就是說一個表就得寫一個函數,不過方法1的一個取值就要便捷多了。在大多數應用中,也不會存在大量這種合并字符串的需求。廢話完畢,看下面:
定義一個函數

1 create or replace function str_list( str_in in varchar2 )--分類字段 2 return varchar2 3 is 4 str_list varchar2(4000) default null;--連接后字符串 5 str varchar2(20) default null;--連接符號 6 begin 7 for x in ( select TEST.CITY from TEST where TEST.COUNTRY = str_in ) loop 8 str_list := str_list || str || to_char(x.city); 9 str := ', '; 10 end loop; 11 return str_list; 12 end;

?

使用:

1 SQL> select DISTINCT(T.country),list_func1(t.country) from test t; 2 3 COUNTRY LIST_FUNC1(T.COUNTRY) 4 -------------------- ---------------- 5 中國 臺北, 香港, 上海 6 日本 東京, 大阪 7 8 SQL> select t.country,str_list(t.country) from test t GROUP BY t.country; 9 10 11 COUNTRY STR_LIST(T.COUNTRY) 12 -------------------- ----------------------- 13 中國 臺北, 香港, 上海 14 日本 東京, 大阪

?

這個時候,使用分組和求唯一都可以滿足要求。它的原理就是,根據唯一的分組字段country,在函數里面再次查詢該字段對應的所有被合并列,使用PL/SQL將其合并輸出。
3.靈活表函數法 靈活性★★★ 性能★★★ 難度 ★★★
該方法是在方法2的基礎上,使用動態SQL,將表名和字段名稱傳入,從而達到靈活的目的。

1 create or replace function str_list2( key_name in varchar2, 2 key in varchar2, 3 coname in varchar2, 4 tname in varchar2 ) 5 return varchar2 6 as 7 type rc is ref cursor; 8 str varchar2(4000); 9 sep varchar2(2); 10 val varchar2(4000); 11 cur rc; 12 begin 13 open cur for 'select '||coname||' 14 from '|| tname || ' 15 where ' || key_name || ' = :x ' 16 using key; 17 loop 18 fetch cur into val; 19 exit when cur%notfound; 20 str := str || sep || val; 21 sep := ', '; 22 end loop; 23 close cur; 24 return str; 25 end; 26 SQL> select test.country, 27 2 str_list2('COUNTRY', test.country, 'CITY', 'TEST') emplist 28 3 from test 29 4 group by test.country 30 5 / 31 32 33 COUNTRY EMPLIST 34 -------------------- ----------------- 35 中國 臺北, 香港, 上海 36 日本 東京, 大阪

?

4.一條SQL法 靈活性★★★★ 性能★★ 難度 ★★★★
一條SQL的法則是某位大師提出的,大家曾經在某個時期都樂此不彼的尋求各種的問題一條SQL法,但是大師的意思似乎被曲解,很多性能差,可讀性差,靈活差的SQL都是這個原則產物,所謂畫虎不成反成犬類。不過,解決問題始終是第一原則,這里還是給出一個比較有代表性的一條SQL方法。

1 SELECT country,max(substr(city,2)) city 2 FROM 3 (SELECT country,sys_connect_by_path(city,',') city 4 FROM 5 (SELECT country,city,country||rn rchild,country||(rn-1) rfather 6 FROM 7 (SELECT test.country ,test.city,row_number() over (PARTITION BY test.country ORDER BY test.city) rn FROM test)) 8 CONNECT BY PRIOR rchild=rfather START WITH rfather LIKE '%0') 9 GROUP BY country; 10 下面分步解析,有4個FROM,就有4次結果集的操作。 11 step 1 給記錄加上序號rn 12 SQL> SELECT test.country ,test.city,row_number() over (PARTITION BY test.country ORDER BY test.city) rn 13 2 FROM test 14 3 / 15 16 17 COUNTRY CITY RN 18 -------------------- -------------------- ---------- 19 日本 大阪 1 20 日本 東京 2 21 中國 上海 1 22 中國 臺北 2 23 中國 香港 3

?

step 2 創造子節點父節點

1 SQL> SELECT country,city,country||rn rchild,country||(rn-1) rfather 2 2 FROM 3 3 (SELECT test.country ,test.city,row_number() over (PARTITION BY test.country ORDER BY test.city) rn 4 4 FROM test) 5 5 / 6 日本 大阪 日本1 日本0 7 日本 東京 日本2 日本1 8 中國 上海 中國1 中國0 9 中國 臺北 中國2 中國1 10 中國 香港 中國3 中國2 11 step 3 利用sys_connect_by_path生成結果集 12 SELECT country,sys_connect_by_path(city,',') city 13 FROM 14 (SELECT country,city,country||rn rchild,country||(rn-1) rfather 15 FROM 16 (SELECT test.country ,test.city,row_number() over (PARTITION BY test.country ORDER BY test.city) rn FROM test)) CONNECT BY PRIOR rchild=rfather START WITH rfather LIKE '%0' 17 日本 ,大阪 18 日本 ,大阪,東京 19 中國 ,上海 20 中國 ,上海,臺北 21 中國 ,上海,臺北,香港 22 step 4 最終步驟,篩選結果集合 23 SQL> SELECT country,max(substr(city,2)) city 24 2 FROM 25 3 (SELECT country,sys_connect_by_path(city,',') city 26 4 FROM 27 5 (SELECT country,city,country||rn rchild,country||(rn-1) rfather 28 6 FROM 29 7 (SELECT test.country ,test.city,row_number() over (PARTITION BY test.country ORDER BY test.city) rn 30 8 FROM test)) 31 9 CONNECT BY PRIOR rchild=rfather START WITH rfather LIKE '%0') 32 10 GROUP BY country; 33 34 35 COUNTRY CITY 36 -------------------- ------- 37 中國 上海,臺北,香港 38 日本 大阪,東京

?


可謂是,7歪8搞,最后還是弄出來了,呵呵。 PS:(邏輯上是對的..但是寫的比較繁瑣,可以簡化!)
5.自定義聚合函數 靈活性★★★★★ 性能★★★★★ 難度 ★★★★★
最后一個方法是我認為“王道”的方法,自定義聚合函數。
就如何我在本開始說的,為啥oracle沒有這種聚合函數呢?我也不知道,但oracle提供了聚合函數的API可以讓我方便的自己定義聚合函數。
詳細可以看Oracle Data Catridge guide這個文檔。連接如下:
http://www.oracle.com.cn/other/9ionlinedoc/appdev.920/a96595/toc.htm
下面給出一個簡單的例子:

1 SQL> SELECT t.country,strcat(t.city) FROM test t GROUP BY t.country; 2 3 4 COUNTRY STRCAT(T.CITY) 5 -------------------- ------------------ 6 日本 東京,大阪 7 中國 臺北,香港,上海 8 簡單吧,和官方的函數一樣的便捷高效。 9 函數: 10 CREATE OR REPLACE FUNCTION strcat(input varchar2 ) 11 RETURN varchar2 12 PARALLEL_ENABLE AGGREGATE USING strcat_type; 13 TYPE: 14 create or replace type strcat_type as object ( 15 cat_string varchar2(4000), 16 static function ODCIAggregateInitialize(cs_ctx In Out strcat_type) return number, 17 member function ODCIAggregateIterate(self In Out strcat_type,value in varchar2) return number, 18 member function ODCIAggregateMerge(self In Out strcat_type,ctx2 In Out strcat_type) return number,member function ODCIAggregateTerminate(self In Out strcat_type,returnValue Out 19 varchar2,flags in number) return number)

?

6.待發掘...

PS: 在 oracle 10g下,可以使用以下系統函數:

1 select id,WMSYS.WM_CONCAT(oid) oid 2 from table1 3 group by id

?

總結,合并字符串還有更多的方法希望大家能發掘,本文的目的主要是拋磚引玉,如果有新的發現我會繼續更新方法。

需要注意的問題是,本文采用varchar2為例子,所以長度有限制,oracle的版本對方法的實現也影響。

轉載于:https://www.cnblogs.com/zhangwei595806165/p/3142446.html

總結

以上是生活随笔為你收集整理的Oracle 多行记录合并/连接/聚合字符串的几种方法的全部內容,希望文章能夠幫你解決所遇到的問題。

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