SQL:使用 SQL 将两个逗号分隔的字符串拆分为单独的索引行

Posted

技术标签:

【中文标题】SQL:使用 SQL 将两个逗号分隔的字符串拆分为单独的索引行【英文标题】:SQL: Split two comma separated strings into separate indexed rows using SQL 【发布时间】:2018-01-15 07:44:58 【问题描述】:

我存储的数据使我的查询返回以下内容:

EntryNum  FieldNames                FootnoteIDs
1         FieldA, FieldA, FieldB    F1, F3, F2
2         FieldA, FieldA, FieldB    F1, F4, F2
3         FieldB, FieldC, FieldD    F1, F12, F13

我想按如下方式返回:

EntryNum  FieldName  FootnoteID
1         FieldA     F1
1         FieldA     F3
1         FieldB     F2
2         FieldA     F1
2         FieldA     F4
2         FieldB     F2
3         FieldB     F1
3         FieldC     F12
3         FieldD     F13

用于此的 SQL 会是什么样子?不使用用户定义的函数或 SPLIT_STRING 是否可行?

我找到的最接近解决方案的是: Split comma separated string table row into separate rows using TSQL,但这没有我需要的双重分裂行为。更多详细信息 a) 每个条目的字段数或每个条目的脚注 ID 没有限制,并且 b) 我需要匹配的只是字段名称和脚注 ID 的顺序。

【问题讨论】:

看起来这里已经回答了这个问题,该技术应该能够为您需要的多列提供相应的逐行结果。 ***.com/questions/19073500/… 我已经看过那个答案,但它不适用于这个用例。它返回一个包含所有逗号分隔项目的单列,而我需要将两个不同字段中的项目相关地放入行中。 对于 SQL Server:考虑他在此处详细介绍的各种用户定义函数方法sqlperformance.com/2012/07/t-sql-queries/split-strings 我正在处理的服务器不允许创建/使用用户定义的函数,所以很遗憾,这在这里是不可能的。 【参考方案1】:

当问题被标记为 MySQL 时提供此答案。

您的预期结果要求 fieldname 与 FootnoteID 存在一对一的关系,因此定位一个连接列的每个部分的逻辑与第二个所需的逻辑相同。换句话说:如果您的数据在两个逗号分隔的列中具有相同数量的部分,则可以使用一种方法来拆分两者:

CREATE TABLE Table1
    (`EntryNum` int, `FieldNames` varchar(22), `FootnoteIDs` varchar(12))
;

INSERT INTO Table1
    (`EntryNum`, `FieldNames`, `FootnoteIDs`)
VALUES
    (1, 'FieldA, FieldA, FieldB', 'F1, F3, F2'),
    (2, 'FieldA, FieldA, FieldB', 'F1, F4, F2'),
    (3, 'FieldB, FieldC, FieldD', 'F1, F12, F13')
;

查询 1

SELECT
      t.EntryNum
    , SUBSTRING_INDEX(SUBSTRING_INDEX(t.FieldNames, ',', n.n), ',', -1) FieldName
    , SUBSTRING_INDEX(SUBSTRING_INDEX(t.FootnoteIDs, ',', n.n), ',', -1) FootnoteID
FROM table1 t 
CROSS JOIN  (
   SELECT a.N + b.N * 10 + 1 n
   FROM  (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
   CROSS JOIN (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
  ) n
WHERE n.n <= 1 + (LENGTH(t.FieldNames) - LENGTH(REPLACE(t.FieldNames, ',', '')))
order by t.EntryNum, n.n

看到这个SQL Fiddle

| EntryNum | FieldName | FootnoteID |
|----------|-----------|------------|
|        1 |    FieldA |         F1 |
|        1 |    FieldA |         F3 |
|        1 |    FieldB |         F2 |
|        2 |    FieldA |         F1 |
|        2 |    FieldA |         F4 |
|        2 |    FieldB |         F2 |
|        3 |    FieldB |         F1 |
|        3 |    FieldC |        F12 |
|        3 |    FieldD |        F13 |

注意上面的查询是SQL split comma separated row 答案的派生词,该答案指的是永久“计数表”而不是如上所述的动态子查询 (n) 的好处。

【讨论】:

抱歉,我错误地将我的问题标记为针对 mysql,而实际上我使用的是 SQL Server。 SQL Server 中似乎不存在 SUBSTRING_INDEX 函数。不过,这看起来是正确的想法! SQL Server 是否有等效的实现? 这是一个相当错误的标签! (请在以后仔细检查)。它可以在 SQL Server 中实现 - 但您使用的是什么版本(这可能会有所不同)。注意:研究“拆分字符串函数 tsql”。从 SQL Server 2016 开始,有一个内置函数 docs.microsoft.com/en-us/sql/t-sql/functions/… 当我运行服务器版本查询时,它告诉我我正在使用 SQL Server 2016,但也无法识别 split_string 函数。有谁知道为什么会这样?我检查了兼容性级别,它说它是 130。 是错字吗?函数是 string_split 而不是 split_string。

以上是关于SQL:使用 SQL 将两个逗号分隔的字符串拆分为单独的索引行的主要内容,如果未能解决你的问题,请参考以下文章

如何根据一个字段是不是包含oracle sql中的逗号分隔字符串将单行拆分为多行?

SQL拆分逗号分隔的字符串

使用 Oracle SQL 将可变长度分隔字符串拆分为列

使用 WHERE IN SQL 子句将字符串值从单个值拆分为多个值以获取数据

将逗号分隔的字符串拆分为mysql中的行

我可以使用 SQL 将存储为 CSV(逗号分隔值)的表列的内容拆分为新表中的单独行吗?