字段拆分多行的需求

點擊標題下「藍色微信名」可快速關注

預計閱讀時間:4分鐘微信


老婆昨兒提了一個問題,一張表中的字段,存儲的是用","分隔的字符串,是否能夠按照",",拆成多行?函數


舉個例子,TBL_ROW表,三個字段,其中POS字段,包含以","分隔的字符串,需求就是將POS中","分隔的字符串,連同NAME和NATIONALITY,拆成多行,spa

CREATE TABLE TBL_ROW
(
 NAME  VARCHAR2(10),
 NATIONALITY  VARCHAR2(10),
 POS  VARCHAR2(200)
);

INSERT INTO TBL_ROW VALUES('張稀哲','中國','前衛,前腰,前鋒');
INSERT INTO TBL_ROW VALUES('奧古斯托','巴西','後腰,前腰,前衛,前鋒');
INSERT INTO TBL_ROW VALUES('比埃拉','西班牙','前衛,前腰');

SELECT * FROM tbl_row;
NAME    NATIONALITY  POS
------- -----------  ----------------------
傲骨    巴西       後腰,前腰,前衛,前鋒
張稀哲   中國       前衛,前腰,前鋒
比埃拉   西班牙      前腰,前衛


第一種寫法:.net

使用正則函數,解析","分隔的字符,使用connect by層級查詢,distinct進行去重的操做,設計

select DISTINCT NAME, nationality,
regexp_substr(pos, '[^,]+',1,level)
FROM tbl_row
connect by level <= length(decode(substr(pos,-1),',',substr(pos,1,length(pos)-1),pos)) - length(REPLACE(pos,',',''))+1
ORDER BY NAME;


對應的執行計劃,code


第二種寫法:regexp

使用substr分隔字符串,使用connect by層級查詢,orm

SELECT NAME,nationality,substr(a.pos, instr(a.pos, ',', 1, levels.lvl) + 1, instr(a.pos, ',', 1, levels.lvl + 1) -(instr(a.pos, ',', 1, levels.lvl) + 1))
FROM
(SELECT NAME,',' || pos || ',' AS pos,nationality,length(pos) - nvl(length(REPLACE(pos, ',')), 0) + 1 AS cnt
FROM tbl_row) a,
(SELECT rownum AS lvl
FROM (SELECT MAX(length(pos || ',') - nvl(length(REPLACE(pos, ',')), 0)) max_len FROM tbl_row)
CONNECT BY LEVEL <= max_len) levels
WHERE levels.lvl <= a.cnt
ORDER BY NAME;


對應的執行計劃,blog


獲得的結果相同,ci

NAME    NATIONALITY  POS
------- -----------  -------
傲骨    巴西       前腰
傲骨    巴西       前衛
傲骨    巴西       前鋒
傲骨    巴西       後腰
張稀哲   中國       前鋒
張稀哲   中國       前腰
張稀哲   中國       前衛
比埃拉   西班牙     前衛
比埃拉   西班牙     前腰


總結一下,

1. 第二種寫法相比第一種寫法,略優一些,數據量小,區分不明顯。

2. POS字段的設計,很是不合理,從理論上講,不符合第三範式,不是原子拆分,所以纔可能有這種需求。

3. 經驗告訴咱們,老婆的問題,不能不重視,以最小的代價,先解決了再說。

本文分享自微信公衆號 - bisal的我的雜貨鋪(gh_e8769c7350b1)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索