我有这个专栏:
names
John, Mary
Joseph
Eleanor, Sophia, Dani
我想要这个输出:
names
John
Mary
Joseph
Eleanor
Sophia
Dani
并且它应该包含 SUBSTRING_INDEX 函数
您可以使用递归 CTE:
with recursive cte as (
select ' ' as name, concat(names, ',') as names, 1 as lev
from t
union all
select substring_index(names, ',', 1),
substr(names, instr(names, ',') + 2), lev + 1
from cte
where names like '%,%'
)
select name
from cte
where lev > 1;
这里是一个db<>小提琴。
一个选项使用递归查询:
with recursive
data as (select concat(names, ', ') names from mytable),
cte as (
select
substring(names, 1, locate(', ', names) - 1) word,
substring(names, locate(', ', names) + 2) names
from data
union all
select
substring(names, 1, locate(', ', names) - 1) word,
substring(names, locate(', ', names) + 2) names
from cte
where locate(', ', names) > 0
)
select word from cte
|词| | :------ | |约翰 | |约瑟夫| |埃莉诺| |玛丽| |索菲亚 | |丹妮 |
使用SUBSTRING_INDEX函数:
SELECT
TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(names,',',x.x),',',-1)) as name
FROM mytable
CROSS JOIN (SELECT 1 as x union all select 2 union all select 3 union all select 4) x
WHERE x.x <= LENGTH(names)-LENGTH(REPLACE(names,',',''))+1
(简短)解释:
函数
SUBSTRING_INDEX(names,',',2)
将返回字符串names
中的前两个名称。当对最后一个参数使用 -1 时,您将仅获得该字符串的最后一个元素,因此您最终会得到名称中的第二个名称。
此简单示例中的
CROSS JOIN
将每个记录的名称数量限制为 4 个。当您需要更多名称时,应该扩展它,或者可以使用对仅包含整数的表的引用。
参见:DBFIDDLE
对 Gordon Linoff 的 答案的稍微扩展,结合他的 其他答案,以涵盖原始表格中 逗号后没有空格的情况:
with recursive names_cleaned as (
select replace(replace(names, ', ', ','), ',', ', ') nc
from t),
cte as (
select ' ' as name, concat(nc, ',') as nc, 1 as lev
from names_cleaned
union all
select substring_index(nc, ',', 1),
substr(nc, instr(nc, ',') + 2), lev + 1
from cte
where nc like '%,%'
)
select name
from cte
where lev > 1;
还值得注意的是:如何结合递归CTE和普通CTE
上述答案的稍微调整版本:
create or replace procedure splitstring(
value TEXT,
delim VARCHAR(12)
)
BEGIN
with recursive
data as (select CONCAT(value,delim) as entries),
cte as (
select
substring(entries, 1, locate(delim, entries) - LENGTH(delim)) entry,
substring(entries, locate(delim, entries) + LENGTH(delim)) entries
from data
union all
select
substring(entries, 1, locate(delim, entries) - LENGTH(delim)) entry,
substring(entries, locate(delim, entries) + LENGTH(delim)) entries
from cte
where locate(delim, entries) > 0
)
select entry from cte where length(entry) > 0;
END
使用方法
call splitrec('Alex,Stitch,Cain,Denton', ',')
delimeter
(最大长度为12个字符,可以根据需要进行调整)。select REPLACE(REPLACE(REPLACE(very_messy_string_value, ' ', ''), '\t', ''), '\n', '');