英文:
Turning related Comma Separated strings into individual rows with multiple columns with one to many
问题
我在查看帖子将相关的逗号分隔字符串转换为具有多列的单独行。这对于我的情况非常有效,当数据Data是一对一关联数据时。但是我需要更多像Data到Many RelatedDate的数据。我使用[]将每个RelatedData分组到Data的每个部分。
我想返回如下的行:
| SomeID | OtherID | Data | RelatedData |
+----------------+-------------+------+-------------+
| abcdef-..... | cdef123-... | 18 | xxx |
| abcdef-..... | cdef123-... | 20 | xxxx |
| abcdef-..... | cdef123-... | 20 | |
| abcdef-..... | cdef123-... | 22 | yyy |
| abcdef-..... | 4554a24-... | 17 | a |
| abcdef-..... | 4554a24-... | 19 | bb |
| ... | ... | ... | ... |
我尝试修改帖子中的一个答案以满足我的需求,但我没有成功,因为它将我的数据推送到新行中。
英文:
I was looking at the post Turning related Comma Separated strings into individual rows with multiple columns. This works great for me when the data Data is one to one Related Data. But I need more data like Data to Many RelatedDate. I use [] to group each RelatedData to each section of Data.
| SomeID | OtherID | Data | RelatedData |
+----------------+-------------+-----------+-------------+
| abcdef-..... | cdef123-... | 18,20,22 | [xxx,xxxx],[xxxx],[yyy]|
| abcdef-..... | 4554a24-... | 17,19 | [a],[bb] |
| 987654-..... | 12324a2-... | 13,19,20 | [r],展开收缩,[t] |
I want to return rows like the following:
| SomeID | OtherID | Data | RelatedData |
+----------------+-------------+------+-------------+
| abcdef-..... | cdef123-... | 18 | xxx |
| abcdef-..... | cdef123-... | 20 | xxxx |
| abcdef-..... | cdef123-... | 20 | |
| abcdef-..... | cdef123-... | 22 | yyy |
| abcdef-..... | 4554a24-... | 17 | a |
| abcdef-..... | 4554a24-... | 19 | bb |
| ... | ... | ... | ... |
I've tried to modify one of the answers from the post to fit my needs but I have no luck as it is pushing my data to a new row.
;WITH cte AS (
SELECT SomeId, OtherId, TRIM(cs1.Value) AS DataValue, TRIM(REPLACE(REPLACE(cs2.Value, '[', ''), ']', '')) AS RelatedDataValue,
DataItemNumber = ROW_NUMBER() OVER (PARTITION BY t.SomeId, t.OtherId, cs1.Value ORDER BY (SELECT NULL)),
RelatedDataItemNumber = ROW_NUMBER() OVER (PARTITION BY t.SomeId, t.OtherId, cs2.Value ORDER BY (SELECT NULL))
FROM t
CROSS APPLY STRING_SPLIT(Data, ',') cs1
CROSS APPLY STRING_SPLIT(REPLACE(REPLACE(RelatedData, '[', ''), ']', ''), ',') cs2
)
SELECT cte.SomeId, cte.OtherId, cte.DataValue, cte.RelatedDataValue
FROM cte
WHERE cte.DataItemNumber = cte.RelatedDataItemNumber
ORDER BY cte.SomeId, cte.OtherId, cte.DataItemNumber;
答案1
得分: 0
以下是您要翻译的内容:
"This may only take you one step further, as it appears you have "related data" that is a one to many relationship to data. However this may assist. One of the great problems with string_split is that it does NOT supply the index reference of each split and so to get around this you can emulate this by using row_number. Alternatively find a "split string" user defined function and that does output the index (these do exist). So without going into too much detail, and using split_string, you can align the parts to each other this way:
Note I replaced ,[
and [
in RelatedData so that only ]
is needed as the delimiter.
--DDL
CREATE TABLE T (
SomeID VARCHAR(255),
OtherID VARCHAR(255),
Data VARCHAR(255),
RelatedData VARCHAR(255)
);
--DML !! NB SomeID is now unique !!
INSERT INTO T (SomeID, OtherID, Data, RelatedData)
VALUES
('abcdef-1....', 'cdef123-...', '18,20,22', '[xxx,xxxx],[xxxx],[yyy]'),
('abcdef-2....', '4554a24-...', '17,19', '[a],[bb]'),
('987654-3....', '12324a2-...', '13,19,20', '[r],
status
3 rows affected
update T
set RelatedData = replace(replace(RelatedData,',[',''),'[','')
status
3 rows affected
select * from t
SomeID | OtherID | Data | RelatedData |
---|---|---|---|
abcdef-1.... | cdef123-... | 18,20,22 | xxx,xxxx]xxxx]yyy] |
abcdef-2.... | 4554a24-... | 17,19 | a]bb] |
987654-3.... | 12324a2-... | 13,19,20 | r]s]t] |
select t.someID, cs1.*, row_number() over(partition by t.SomeID order by (select 1)) rn
FROM t
CROSS APPLY STRING_SPLIT(Data, ',') cs1
someID | value | rn |
---|---|---|
987654-3.... | 13 | 1 |
987654-3.... | 19 | 2 |
987654-3.... | 20 | 3 |
abcdef-1.... | 18 | 1 |
abcdef-1.... | 20 | 2 |
abcdef-1.... | 22 | 3 |
abcdef-2.... | 17 | 1 |
abcdef-2.... | 19 | 2 |
select t.someID, cs2.*, row_number() over(partition by t.SomeID order by (select 1)) rn
FROM t
CROSS APPLY STRING_SPLIT(RelatedData, ']') cs2
someID | value | rn |
---|---|---|
987654-3.... | r | 1 |
987654-3.... | s | 2 |
987654-3.... | t | 3 |
987654-3.... | 4 | |
abcdef-1.... | xxx,xxxx | 1 |
abcdef-1.... | xxxx | 2 |
abcdef-1.... | yyy | 3 |
abcdef-1.... | 4 | |
abcdef-2.... | a | 1 |
abcdef-2.... | bb | 2 |
abcdef-2.... | 3 |
with pdata as (
select t.someID, cs1., row_number() over(partition by t.SomeID order by (select 1)) rn
FROM t
CROSS APPLY STRING_SPLIT(Data, ',') cs1
)
, prelated as (
select t.someID, cs2., row_number() over(partition by t.SomeID order by (select 1)) rn
FROM t
CROSS APPLY STRING_SPLIT(RelatedData, ']') cs2
)
select
*
from pdata
left join prelated on pdata.SomeID = prelated.SomeID
and pdata.rn = prelated.rn
order by 1,2
Note I believe that 18 may need to be further divided using a final string_split - but this varies to what is shown in the question.
with pdata as (
select t.someID, cs1., row_number() over(partition by t.SomeID order by (select 1)) rn
FROM t
CROSS APPLY STRING_SPLIT(Data, ',') cs1
)
, prelated as (
select t.someID, cs2., row_number() over(partition by t.SomeID order by (select 1)) rn
FROM t
CROSS APPLY STRING_SPLIT(RelatedData, ']') cs2
)
select
pdata.SomeID
, pdata.value as data
, cs3.value as related
from pdata
inner join prelated on pdata.SomeID = prelated.SomeID
and pdata.rn = prelated.rn
CROSS APPLY STRING_SPLIT(prelated.value, ',') cs3
order by 1,2
英文:
This may only take you one step further, as it appears you have "related data" that is a one to many relationship to data. However this may assist. One of the great problems with string_split is that it does NOT supply the index reference of each split and so to get around this you can emulate this by using row_number. Alternatively find a "split string" user defined function and that does output the index (these do exist). So without going into too much detail, and using split_string, you can align the parts to each other this way:
Note I replaced ,[
and [
in RelatedData so that only ]
is needed as the delimiter.
--DDL
CREATE TABLE T (
SomeID VARCHAR(255),
OtherID VARCHAR(255),
Data VARCHAR(255),
RelatedData VARCHAR(255)
);
--DML !! NB SomeID is now unique !!
INSERT INTO T (SomeID, OtherID, Data, RelatedData)
VALUES
('abcdef-1....', 'cdef123-...', '18,20,22', '[xxx,xxxx],[xxxx],[yyy]'),
('abcdef-2....', '4554a24-...', '17,19', '[a],[bb]'),
('987654-3....', '12324a2-...', '13,19,20', '[r],展开收缩,[t]');
3 rows affected
update T
set RelatedData = replace(replace(RelatedData,',[',''),'[','')
3 rows affected
select * from t
SomeID | OtherID | Data | RelatedData |
---|---|---|---|
abcdef-1.... | cdef123-... | 18,20,22 | xxx,xxxx]xxxx]yyy] |
abcdef-2.... | 4554a24-... | 17,19 | a]bb] |
987654-3.... | 12324a2-... | 13,19,20 | r]s]t] |
select t.someID, cs1.*, row_number() over(partition by t.SomeID order by (select 1)) rn
FROM t
CROSS APPLY STRING_SPLIT(Data, ',') cs1
someID | value | rn |
---|---|---|
987654-3.... | 13 | 1 |
987654-3.... | 19 | 2 |
987654-3.... | 20 | 3 |
abcdef-1.... | 18 | 1 |
abcdef-1.... | 20 | 2 |
abcdef-1.... | 22 | 3 |
abcdef-2.... | 17 | 1 |
abcdef-2.... | 19 | 2 |
select t.someID, cs2.*, row_number() over(partition by t.SomeID order by (select 1)) rn
FROM t
CROSS APPLY STRING_SPLIT(RelatedData, ']') cs2
someID | value | rn |
---|---|---|
987654-3.... | r | 1 |
987654-3.... | s | 2 |
987654-3.... | t | 3 |
987654-3.... | 4 | |
abcdef-1.... | xxx,xxxx | 1 |
abcdef-1.... | xxxx | 2 |
abcdef-1.... | yyy | 3 |
abcdef-1.... | 4 | |
abcdef-2.... | a | 1 |
abcdef-2.... | bb | 2 |
abcdef-2.... | 3 |
with pdata as (
select t.someID, cs1.*, row_number() over(partition by t.SomeID order by (select 1)) rn
FROM t
CROSS APPLY STRING_SPLIT(Data, ',') cs1
)
, prelated as (
select t.someID, cs2.*, row_number() over(partition by t.SomeID order by (select 1)) rn
FROM t
CROSS APPLY STRING_SPLIT(RelatedData, ']') cs2
)
select
*
from pdata
left join prelated on pdata.SomeID = prelated.SomeID
and pdata.rn = prelated.rn
order by 1,2
someID | value | rn | someID | value | rn |
---|---|---|---|---|---|
987654-3.... | 13 | 1 | 987654-3.... | r | 1 |
987654-3.... | 19 | 2 | 987654-3.... | s | 2 |
987654-3.... | 20 | 3 | 987654-3.... | t | 3 |
abcdef-1.... | 18 | 1 | abcdef-1.... | xxx,xxxx | 1 |
abcdef-1.... | 20 | 2 | abcdef-1.... | xxxx | 2 |
abcdef-1.... | 22 | 3 | abcdef-1.... | yyy | 3 |
abcdef-2.... | 17 | 1 | abcdef-2.... | a | 1 |
abcdef-2.... | 19 | 2 | abcdef-2.... | bb | 2 |
Note I believe that 18 may need to be further divided using a final string_split - but this varies to what is shown in the question.
with pdata as (
select t.someID, cs1.*, row_number() over(partition by t.SomeID order by (select 1)) rn
FROM t
CROSS APPLY STRING_SPLIT(Data, ',') cs1
)
, prelated as (
select t.someID, cs2.*, row_number() over(partition by t.SomeID order by (select 1)) rn
FROM t
CROSS APPLY STRING_SPLIT(RelatedData, ']') cs2
)
select
pdata.SomeID
, pdata.value as data
, cs3.value as related
from pdata
inner join prelated on pdata.SomeID = prelated.SomeID
and pdata.rn = prelated.rn
CROSS APPLY STRING_SPLIT(prelated.value, ',') cs3
order by 1,2
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论