字段拆分多行的需求

点击标题下「蓝色微信名」可快速关注

预计阅读时间: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源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索