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

时间:2021-02-21 00:23:59

I have data stored such that my query returns the following:

我存储了数据,以便我的查询返回以下内容:

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

I'd like to return this as follows:

我想按如下方式返回:

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

What would the SQL for this look like? Is it doable without using either a user-defined function or SPLIT_STRING?

SQL的外观是什么样的?如果不使用用户定义的函数或SPLIT_STRING,它是否可行?

The closest I found to a solution was here: Split comma separated string table row into separate rows using TSQL, but that doesn't have the dual splitting behavior I need. Further details a) there isn't a limit to the number of fields per Entry or FootnoteIDs per entry, and b) it's just the order of the FieldNames and FootnoteIDs that I need matched.

我找到的最接近解决方案的地方是:使用TSQL将逗号分隔的字符串表行拆分为单独的行,但这不具备我需要的双重拆分行为。进一步的细节a)每个条目的字段数或每个条目的FootnoteID没有限制,b)它只是我需要匹配的FieldNames和FootnoteID的顺序。

1 个解决方案

#1


0  

This answer provided when the question was tagged for MySQL.

当问题被标记为MySQL时,提供了这个答案。

Your expected result requires that there is a one-to-one relationship of fieldname to FootnoteID, so the logic to locate each part of one concatenated colunm is the same as that required for the second. Put another way: If your data has an equal number of parts in both the comma separated columns then a single method to split both can be used:

您的预期结果要求fieldname与FootnoteID之间存在一对一的关系,因此查找一个连续colunm的每个部分的逻辑与第二个所需的逻辑相同。换句话说:如果您的数据在逗号分隔的列中具有相同数量的部分,则可以使用单个方法来拆分它们:

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')
;

Query 1:

查询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

See this SQL Fiddle

看到这个SQL小提琴

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

Note the query above is a derivative of the answer at SQL split comma separated row and that answer refers to the benefits of a permanent "tally table" instead of the dynamic subquery (n) as seen above.

注意上面的查询是SQL split逗号分隔行的答案的衍生物,该答案指的是永久“计数表”而不是动态子查询(n)的好处,如上所示。

#1


0  

This answer provided when the question was tagged for MySQL.

当问题被标记为MySQL时,提供了这个答案。

Your expected result requires that there is a one-to-one relationship of fieldname to FootnoteID, so the logic to locate each part of one concatenated colunm is the same as that required for the second. Put another way: If your data has an equal number of parts in both the comma separated columns then a single method to split both can be used:

您的预期结果要求fieldname与FootnoteID之间存在一对一的关系,因此查找一个连续colunm的每个部分的逻辑与第二个所需的逻辑相同。换句话说:如果您的数据在逗号分隔的列中具有相同数量的部分,则可以使用单个方法来拆分它们:

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')
;

Query 1:

查询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

See this SQL Fiddle

看到这个SQL小提琴

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

Note the query above is a derivative of the answer at SQL split comma separated row and that answer refers to the benefits of a permanent "tally table" instead of the dynamic subquery (n) as seen above.

注意上面的查询是SQL split逗号分隔行的答案的衍生物,该答案指的是永久“计数表”而不是动态子查询(n)的好处,如上所示。