描述
上面一篇博客说了如何把逗号拼接的字符串中的id逐个替换成对应的人名,现在新的需求是 将逗号拼接的字符串拆分程 逗号数量的数据行
比如 原始记录是
id | executor |
---|---|
1 | 11,22,33,44 |
那么拆分后的效果是
id | executor |
---|---|
1 | 11 |
1 | 22 |
1 | 33 |
1 | 44 |
实现方案
两种方式
- 递归cte表达式
- 和特定序列做笛卡尔积 ,从结果集里筛选
第一种方案对逗号没有数量限制,
第二种方案由于需要自定义序列,逗号的数量有限制
下面给出具体实现
第一种
WITH RECURSIVE SplitExecutor AS (
-- 基础部分:选择第一部分的值
SELECT
id,
SUBSTRING_INDEX(executor, ',', 1) AS executor,
SUBSTRING(executor, LENGTH(SUBSTRING_INDEX(executor, ',', 1)) + 2) AS remaining
FROM (select 1 as id ,'1,2,3,4' as executor from dual )A
UNION ALL
-- 递归部分:继续拆分剩余的部分
SELECT
id,
SUBSTRING_INDEX(remaining, ',', 1) AS executor,
SUBSTRING(remaining, LENGTH(SUBSTRING_INDEX(remaining, ',', 1)) + 2) AS remaining
FROM SplitExecutor
WHERE remaining != ''
)
SELECT id, executor,remaining
FROM SplitExecutor
ORDER BY id;
从第一行记录到最后ramaining条件不满足, 上面图片比较生动的解释了递归的执行过程,第一行是sql中 union all的上面的查询部分, 然后将该查询结果作为数据集 传递给下面的部分,直到下面的部分中的where条件不满足,亦或者 下面的查询部分查不出记录 为止。
第二种
with task as (
select '1,2,3,4' as title from dual
),
seq as (
select 1 as n
union all
select 2
union all
select 3
union all
select 4
)
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(t.title,',',s.n),',',-1) AS substr
FROM task t
cross join seq s
WHERE LENGTH(t.title)-LENGTH(REPLACE(t.title,',','')) >=s.n -1
这种就比较限制了,超过4个逗号的话 就会出问题了,所以具体需要哪种 自行斟酌