SQL (Maria DB) 将逗号分隔的字符串拆分为行

问题描述 投票:0回答:5

我有这个专栏:

names
John, Mary
Joseph
Eleanor, Sophia, Dani

我想要这个输出:

names
John
Mary
Joseph
Eleanor
Sophia
Dani

并且它应该包含 SUBSTRING_INDEX 函数

sql string csv mariadb recursive-query
5个回答
5
投票

您可以使用递归 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<>小提琴。


3
投票

一个选项使用递归查询:

 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

DB Fiddle 上的演示

|词|
| :------ |
|约翰 |
|约瑟夫|
|埃莉诺|
|玛丽|
|索菲亚 |
|丹妮 |

3
投票

使用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


0
投票

Gordon Linoff答案的稍微扩展,结合他的 其他答案,以涵盖原始表格中 逗号后没有空格的情况:

https://dbfiddle.uk/shW05gvo

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


-1
投票

上述答案的稍微调整版本:

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', '');
© www.soinside.com 2019 - 2024. All rights reserved.