国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數據庫技術|

服務器之家 - 數據庫 - Oracle - Oracle 多行記錄合并/連接/聚合字符串的幾種方法

Oracle 多行記錄合并/連接/聚合字符串的幾種方法

2019-11-08 15:47Oracle教程網 Oracle

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

什么是合并多行字符串(連接字符串)呢,例如: 
SQL> desc test; 
Name Type Nullable Default Comments 
------- ------------ -------- ------- -------- 
COUNTRY VARCHAR2(20) Y 
CITY VARCHAR2(20) Y 

SQL> select * from test; 


COUNTRY CITY 
-------------------- -------------------- 
中國 臺北 
中國 香港 
中國 上海 
日本 東京 
日本 大阪 
要求得到如下結果集: 
------- -------------------- 
中國 臺北,香港,上海 
日本 東京,大阪 
實際就是對字符實現一個聚合功能,我很奇怪為什么Oracle沒有提供官方的聚合函數來實現它呢:) 
下面就對幾種經常提及的解決方案進行分析(有一個評測標準最高★★★★★): 
1.被集合字段范圍小且固定型 靈活性★ 性能★★★★ 難度 ★ 
這種方法的原理在于你已經知道CITY字段的值有幾種,且還不算太多,如果太多這個SQL就會相當的長。。看例子: 
SQL> select t.country, 
2 MAX(decode(t.city,'臺北',t.city||',',NULL)) || 
3 MAX(decode(t.city,'香港',t.city||',',NULL))|| 
4 MAX(decode(t.city,'上海',t.city||',',NULL))|| 
5 MAX(decode(t.city,'東京',t.city||',',NULL))|| 
6 MAX(decode(t.city,'大阪',t.city||',',NULL)) 
7 from test t GROUP BY t.country 
8 / 


COUNTRY MAX(DECODE(T.CITY,'臺北',T.CIT 
-------------------- ------------------------------ 
中國 臺北,香港,上海, 
日本 東京,大阪, 
大家一看,估計就明白了(如果不明白,好好補習MAX DECODE和分組)。這種方法無愧為最笨的方法,但是對某些應用來說,最有效的方法也許就是它。 
2.固定表固定字段函數法 靈活性★★ 性能★★★★ 難度 ★★ 
此法必須預先知道是哪個表,也就是說一個表就得寫一個函數,不過方法1的一個取值就要便捷多了。在大多數應用中,也不會存在大量這種合并字符串的需求。廢話完畢,看下面: 
定義一個函數 
create or replace function str_list( str_in in varchar2 )--分類字段 
return varchar2 
is 
str_list varchar2(4000) default null;--連接后字符串 
str varchar2(20) default null;--連接符號 
begin 
for x in ( select TEST.CITY from TEST where TEST.COUNTRY = str_in ) loop 
str_list := str_list || str || to_char(x.city); 
str := ', '; 
end loop; 
return str_list; 
end; 
使用: 
SQL> select DISTINCT(T.country),list_func1(t.country) from test t; 

COUNTRY LIST_FUNC1(T.COUNTRY) 
-------------------- ---------------- 
中國 臺北, 香港, 上海 
日本 東京, 大阪 

SQL> select t.country,str_list(t.country) from test t GROUP BY t.country; 


COUNTRY STR_LIST(T.COUNTRY) 
-------------------- ----------------------- 
中國 臺北, 香港, 上海 
日本 東京, 大阪 
這個時候,使用分組和求唯一都可以滿足要求。它的原理就是,根據唯一的分組字段country,在函數里面再次查詢該字段對應的所有被合并列,使用PL/SQL將其合并輸出。 
3.靈活表函數法 靈活性★★★ 性能★★★ 難度 ★★★ 
該方法是在方法2的基礎上,使用動態SQL,將表名和字段名稱傳入,從而達到靈活的目的。 
create or replace function str_list2( key_name in varchar2, 
key in varchar2, 
coname in varchar2, 
tname in varchar2 ) 
return varchar2 
as 
type rc is ref cursor; 
str varchar2(4000); 
sep varchar2(2); 
val varchar2(4000); 
cur rc; 
begin 
open cur for 'select '||coname||' 
from '|| tname || ' 
where ' || key_name || ' = :x ' 
using key; 
loop 
fetch cur into val; 
exit when cur%notfound; 
str := str || sep || val; 
sep := ', '; 
end loop; 
close cur; 
return str; 
end; 
SQL> select test.country, 
2 str_list2('COUNTRY', test.country, 'CITY', 'TEST') emplist 
3 from test 
4 group by test.country 
5 / 


COUNTRY EMPLIST 
-------------------- ----------------- 
中國 臺北, 香港, 上海 
日本 東京, 大阪 
4.一條SQL法 靈活性★★★★ 性能★★ 難度 ★★★★ 
一條SQL的法則是某位大師提出的,大家曾經在某個時期都樂此不彼的尋求各種的問題一條SQL法,但是大師的意思似乎被曲解,很多性能差,可讀性差,靈活差的SQL都是這個原則產物,所謂畫虎不成反成犬類。不過,解決問題始終是第一原則,這里還是給出一個比較有代表性的一條SQL方法。 
SELECT country,max(substr(city,2)) city 
FROM 
(SELECT country,sys_connect_by_path(city,',') city 
FROM 
(SELECT country,city,country||rn rchild,country||(rn-1) rfather 
FROM 
(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') 
GROUP BY country; 
下面分步解析,有4個FROM,就有4次結果集的操作。 
step 1 給記錄加上序號rn 
SQL> SELECT test.country ,test.city,row_number() over (PARTITION BY test.country ORDER BY test.city) rn 
2 FROM test 
3 / 


COUNTRY CITY RN 
-------------------- -------------------- ---------- 
日本 大阪 1 
日本 東京 2 
中國 上海 1 
中國 臺北 2 
中國 香港 3 
step 2 創造子節點父節點 
SQL> SELECT country,city,country||rn rchild,country||(rn-1) rfather 
2 FROM 
3 (SELECT test.country ,test.city,row_number() over (PARTITION BY test.country ORDER BY test.city) rn 
4 FROM test) 
5 / 
日本 大阪 日本1 日本0 
日本 東京 日本2 日本1 
中國 上海 中國1 中國0 
中國 臺北 中國2 中國1 
中國 香港 中國3 中國2 
step 3 利用sys_connect_by_path生成結果集 
SELECT country,sys_connect_by_path(city,',') city 
FROM 
(SELECT country,city,country||rn rchild,country||(rn-1) rfather 
FROM 
(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' 
日本 ,大阪 
日本 ,大阪,東京 
中國 ,上海 
中國 ,上海,臺北 
中國 ,上海,臺北,香港 
step 4 最終步驟,篩選結果集合 
SQL> 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 
8 FROM test)) 
9 CONNECT BY PRIOR rchild=rfather START WITH rfather LIKE '%0') 
10 GROUP BY country; 


COUNTRY CITY 
-------------------- ------- 
中國 上海,臺北,香港 
日本 大阪,東京 


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


COUNTRY STRCAT(T.CITY) 
-------------------- ------------------ 
日本 東京,大阪 
中國 臺北,香港,上海 
簡單吧,和官方的函數一樣的便捷高效。 
函數: 
CREATE OR REPLACE FUNCTION strcat(input varchar2 ) 
RETURN varchar2 
PARALLEL_ENABLE AGGREGATE USING strcat_type; 
TYPE: 
create or replace type strcat_type as object ( 
cat_string varchar2(4000), 
static function ODCIAggregateInitialize(cs_ctx In Out strcat_type) return number, 
member function ODCIAggregateIterate(self In Out strcat_type,value in varchar2) return number, 
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 
varchar2,flags in number) return number) 
6.待發掘... 

PS: 在 oracle 10g下,可以使用以下系統函數: 
select id,WMSYS.WM_CONCAT(oid) oid 
from table1 
group by id 
總結,合并字符串還有更多的方法希望大家能發掘,本文的目的主要是拋磚引玉,如果有新的發現我會繼續更新方法。需要注意的問題是,本文采用varchar2為例子,所以長度有限制,oracle的版本對方法的實現也影響。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久韩国 | 81精品国产乱码久久久久久 | 免费a网站 | 91捆绑91紧缚调教91 | 久久久天堂国产精品女人 | 中文字幕日韩视频 | 欧美综合区 | 久久aⅴ乱码一区二区三区 一区二区精品视频 | 91操操| 中国av在线免费观看 | 国产精品欧美久久久久一区二区 | 国产伦精品一区二区三区四区视频 | 九九在线视频 | 午夜欧美精品久久久久 | 中文久久 | 亚洲成人一区二区三区 | 久久久精品欧美 | 99视频精品在线 | 国产馆| 国产精品无码久久久久 | 欧美日韩一区二区在线 | 伊人99热 | 久久久久a | 亚洲综合一二区 | 久久久久久国产精品高清 | 久久爱综合 | 日韩视频免费在线播放 | 亚洲精品视频在线看 | 日本激情视频 | 日本免费精品视频 | 欧美亚洲一区 | 99999色| 午夜av电影 | 91精品国产日韩91久久久久久 | 久久久99精品免费观看 | 日韩视频在线一区 | 国内精品视频在线观看 | 亚洲视频在线播放 | 激情视频网 | 欧美自拍一区 | 欧美永久精品 |