oracle把多行合并成字符串,怎样将Oracle多行转换成字符串?
在做一些比較復(fù)雜的DB數(shù)據(jù)導(dǎo)出時(shí),有時(shí)會(huì)要求“將不固定的多行數(shù)據(jù)組合成一個(gè)字符串返回”。
例子:ISV Portal中就遇到了類似的情況,要求對(duì)于每一個(gè)APP,返回其所屬的所有類目名稱,類目名稱之間用[,]隔開。
本文就用此例子來介紹。在具體陳述實(shí)現(xiàn)方案之前,我們先介紹下我們即將操作的表結(jié)構(gòu):
SQL> desc app_category_link;
Name Type Nullable Default Comments
APP_CATEGORY_LINK_ID VARCHAR2(20) 主關(guān)鍵
APP_ID VARCHAR2(20) 應(yīng)用ID
APP_CATEGORY_ID VARCHAR2(20) 應(yīng)用類別ID
其中字段APP_ID和APP_CATEGORY_ID是一對(duì)多關(guān)系;
對(duì)于該類型的問題,總結(jié)一下大致有如下幾種常見方案:
方案1:sys_connect_by_path + start with 。
。。 connect by 。。。 prior + 分析函數(shù)
從上面的這個(gè)公式中我們可以看出,該方案主要是通過分析函數(shù)和父子級(jí)聯(lián)查詢來完成,一般是一條SQL搞定,比較省事。首先來看幾個(gè)具體的實(shí)現(xiàn)SQL。
具體實(shí)現(xiàn)1:
SELECT app_id,
ltrim(max(sys_connect_by_path(app_category_id, ',')), ',') categ_ids
FROM (SELECT app_id,
app_category_id,
app_category_id || '|' || rn rchild,
app_category_id || '|' || (rn - 1) rfather
FROM (SELECT app_id,
app_category_id,
row_number() over(PARTITION BY app_id ORDER BY app_category_id) rn
FROM app_category_link))
START WITH rfather LIKE '%|0'
CONNECT BY PRIOR rchild = rfather
GROUP BY app_id;
具體實(shí)現(xiàn)2:
select app_id,
ltrim(max(sys_connect_by_path(app_category_id, ',')), ',') categ_ids
from (select t。
app_id,
t。app_category_id,
min(t。app_category_id) over(partition by app_id) categ_min,
(row_number() over(order by app_id, app_category_id)) +
(dense_rank() over(order by app_id)) numid
from app_category_link t)
start with app_category_id = categ_min
connect by numid - 1 = prior numid
group by app_id;
具體實(shí)現(xiàn)3:
select app_id,
ltrim(max(sys_connect_by_path(app_category_id, ',')), ',') categ_ids
from (select t。
app_id,
t。app_category_id,
(row_number()
over(partition by app_id order by app_category_id)) numid
from app_category_link t)
start with numid = 1
connect by numid - 1 = prior numid
and app_id = prior app_id
group by app_id;
具體實(shí)現(xiàn)4:
select app_id,
ltrim(sys_connect_by_path(app_category_id, ','), ',') categ_ids
from (select t。
app_id,
t。
app_category_id,
(row_number()
over(partition by app_id order by app_category_id)) numid
from app_category_link t)
WHERE connect_by_isleaf = 1
start with numid = 1
connect by numid - 1 = prior numid
and app_id = prior app_id;
請(qǐng)注意看4種實(shí)現(xiàn)方式的區(qū)別,下面分別介紹下這4種實(shí)現(xiàn)方式的具體思路;
第1種實(shí)現(xiàn)采用了1個(gè)分析函數(shù)、2次子查詢、一個(gè)like、以及父子級(jí)聯(lián)查詢字段值連接;可以猜測(cè)下性能肯定不咋的,2次子查詢本來已經(jīng)很耗時(shí)了,對(duì)查詢出來的結(jié)果集還要用like匹配,速度就更慢了,此法可以查詢到我們需要的具體數(shù)據(jù),但是效率很低,不可取;他的實(shí)現(xiàn)思路是利用待查詢字段值與各APP下面各類目ID的序列值進(jìn)行組合,并作為父子關(guān)系級(jí)聯(lián)的依據(jù);
第2種實(shí)現(xiàn)采用了3個(gè)分析函數(shù)、1次全表掃描、以及父子級(jí)聯(lián)字段值連接;和第1種實(shí)現(xiàn)比較而言的話效率會(huì)高不少;他的實(shí)現(xiàn)思路是利用各APP對(duì)應(yīng)的最小類目ID作為父子級(jí)聯(lián)的開始點(diǎn),而父子級(jí)聯(lián)的依據(jù)是row_number()+dense_rank(),這樣做主要是為了避免無限循環(huán);
第
3、4兩種實(shí)現(xiàn)思路基本上是一樣的,都是1個(gè)分析函數(shù)、1次全表掃描、以及父子級(jí)聯(lián)字段值連接;從代碼長度來說,比前2種實(shí)現(xiàn)方式簡潔了不少,思路也清晰了很多,直接利用各APP對(duì)應(yīng)類目ID的序列值作為父子級(jí)聯(lián)的開始點(diǎn)和連接依據(jù);但仔細(xì)看看兩者的SQL,會(huì)發(fā)現(xiàn)第3這種方式用到了group by子句,而第4種實(shí)現(xiàn)卻沒有用到,而是在where子句中添加了connect_by_isleaf = 1 的查詢條件;從性能上來看,應(yīng)該是第4種實(shí)現(xiàn)方式更高,但他只能在10g及其以后的版本中才能使用,connect_by_isleaf 字段是10g中新提供的一個(gè)偽列,他可以用來判斷該條記錄是否是樹形記錄的葉節(jié)點(diǎn),不過還在用9i版本的可能就有些可惜了;
綜合以上分析,對(duì)4種實(shí)現(xiàn)方案,個(gè)人推薦使用第
3、4兩種實(shí)現(xiàn)方式,具體哪種可以看所用oracle的版本而定,簡而言之,這種實(shí)現(xiàn)方式優(yōu)雅、簡潔、高效;。
全部
總結(jié)
以上是生活随笔為你收集整理的oracle把多行合并成字符串,怎样将Oracle多行转换成字符串?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle_sod,oracle ge
- 下一篇: c语言中prime的作用,C语言判断素数