提问人:mthom 提问时间:6/2/2023 最后编辑:philipxymthom 更新时间:6/2/2023 访问量:40
将相关的逗号分隔字符串转换为具有多列和一对多的单个行
Turning related Comma Separated strings into individual rows with multiple columns with one to many
问:
我正在看帖子将相关的逗号分隔字符串转换为具有多列的单独行。当数据数据是一对一的相关数据时,这对我来说非常有用。但是我需要更多的数据,例如 Data to Many RelatedDate。我使用 [] 将每个 RelatedData 分组到数据的每个部分。
| 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],[s],[t] |
我想返回如下所示的行:
| 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 |
| ... | ... | ... | ... |
我试图修改帖子中的一个答案以满足我的需求,但我没有运气,因为它将我的数据推送到新行。
;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;
答:
0赞
Adrian Maxwell
6/2/2023
#1
这可能只会让您更进一步,因为您似乎拥有与数据的一对多关系的“相关数据”。但是,这可能会有所帮助。string_split 的一大问题是它不提供每个拆分的索引引用,因此要解决这个问题,您可以使用 row_number 来模拟它。或者,找到一个“拆分字符串”用户定义的函数,该函数确实输出索引(这些确实存在)。因此,在不涉及太多细节的情况下,使用split_string,您可以以这种方式将零件相互对齐:
注意:我在 RelatedData 中替换了 and,因此只需要将其作为分隔符。,[
[
]
--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],[s],[t]');
3 rows affected
update T
set RelatedData = replace(replace(RelatedData,',[',''),'[','')
3 rows affected
select * from t
SomeID | 其他 ID | 数据 | 相关数据 |
---|---|---|---|
abcdef-1.... | cdef123-... | 18,20,22 | xxx,xxxx]xxxx]yyy] |
abcdef-2.... | 4554a24-... | 17,19 | a]bb] |
987654-3.... | 12324一2-... | 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 | 价值 | 注册护士 |
---|---|---|
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 | 价值 | 注册护士 |
---|---|---|
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.... | 一个 | 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 | 价值 | 注册护士 | someID | 价值 | 注册护士 |
---|---|---|---|---|---|
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.... | 一个 | 1 |
abcdef-2.... | 19 | 2 | abcdef-2.... | BB型 | 2 |
请注意,我认为 18 可能需要使用最终string_split进一步划分 - 但这因问题中显示的内容而异。
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
评论