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)的好处,如上所示。