DB2遞歸實現字符串分組連接操作
db2中的遞歸查詢使用with來實現,也稱為公共表達式,公共表達式在select語句的開始部分采用with子句的形式,在使用公共表達式的查詢中可以多次使用它,並且公共表達式還可以通過取別名來連接到他本身,這樣的話就可以達到循環的目的。
遞歸查詢通常有3個部分需要定義:
一:一個公共表達式形式的虛擬表。
二:一個初始化表。
三:一個與虛擬表進行完全內連接的輔助表。
需要使用UNION all合並上邊3個查詢,然后用select從遞歸輸出中得到最終的結果。
大體上如下形式
with XX(x1,x2,x3) as -------@0
(
select a.s,a.s1 from a ----@1
union all ----@2
select * from a,xx where a.s=xx.x1 ------@3
)
select ... from xx where .... -------@4
@0:為with體,即虛擬表
@1:為初始化表,這里需要定義初始化的一些行,也就是你遞歸的出發點,或者說父行,這部分邏輯只執行一次,它的結果作為虛擬表遞歸的初始化內容。
@2:這里必須用UNION all
@3:這里需要定義遞歸的條件(輔助表),這里定義遞歸的邏輯,需要注意的是父行和子行進行連接的時候邏輯一定要清楚父子關系,不然很容易變成死循環的,這里首先將初始化表的結果作為條件進行查詢,在把執行的結果添加到虛擬表中,只要這里能查詢出來記錄,那么就會進行下一步遞歸循環。
@4:這里就是對虛擬表的查詢語句。
需求:一張實時表,一個人每到一個地方,就有一條記錄存在,存放樣例:
張三 上海
張三 杭州
.....
要求,按人名進行匯總,將他到過的地方拼接,中間用'#'分隔
數據准備:
--創建表:
CREATE TABLE Recursive_Test
(User_Name VARCHAR(12),
City VARCHAR(12));
--數據插入
INSERT INTO Recursive_Test(User_Name,City)
values ('張三','杭州'),('張三','鄭州'),('李四','杭州'),
('張三','南昌'),('李四','廣州'),('王五','北京');
-----遞歸實現:
WITH Recursive_Test_Par(User_Name,City,Rk_Num) as(
SELECT User_Name,City,ROW_NUMBER() OVER(PARTITION BY User_Name) --分組,生成序列,自我關聯之用
FROM Recursive_Test
),
City_Join(User_Name,City,R_Num) as(
SELECT User_Name,CAST(City AS VARCHAR(100)),Rk_Num from Recursive_Test_Par WHERE Rk_Num=1
UNION ALL
SELECT a1.User_Name,CAST(a1.City||'#'||b1.City AS VARCHAR(100)),a1.R_Num+1
from City_Join a1,Recursive_Test_Par b1
WHERE a1.User_Name=b1.User_Name and a1.R_Num=b1.Rk_Num-1
)
SELECT a.User_name,a.City FROM City_Join a INNER JOIN
(SELECT User_Name,max(R_Num) R_Num from City_Join
GROUP BY User_Name) b
ON a.User_name=b.User_name and a.R_Num=b.R_Num;
--結果:
王五
北京
李四
杭州#廣州
張三
杭州#鄭州#南昌
實戰例子
表說明
ID 巡檢組ID INTEGER
NAME 巡檢組名稱
HYPO 父節點ID, ID=-1 為根節點
TYPE 值=0 是葉子節點 值=1是非葉子節點
ID HYPO NAME TYPE ----------- ----------- --------------------------------------------------------------------------------------------------------------------------------------- ----------- 1 -1 cisco -1 8 1 交換機巡檢 0 429 1 思科設備端口巡檢 0 469 -1 huawei -1 470 469 交換機 0 471 469 huawei-1 -1 472 471 huawei-1-1 -1 473 472 路由器 0
sql:
db2 " with rpl (ID,HYPO,NAME,TYPE) AS ( SELECT ID,HYPO,NAME,TYPE FROM T_CHECK_GROUP WHERE HYPO =-1 UNION ALL SELECT child.ID,child.HYPO,CAST(parent.NAME||'~'||child.NAME AS VARCHAR(100)) ,child.TYPE from rpl parent,T_CHECK_GROUP child WHERE parent.ID=child.HYPO ) select ID,NAME from rpl where TYPE =0"
res:
8 cisco~交換機巡檢 429 cisco~思科設備端口巡檢 470 huawei~交換機 473 huawei~huawei-1~huawei-1-1~路由器