将相关的逗号分隔字符串转换为具有多列的单独行
Turning related Comma Separated strings into individual rows with multiple columns
之前有人问过 Turning a Comma Separated string into individual rows。这对一个专栏很有用,但我有一个扩展问题。如果我想拆分两个(或更多)相关列怎么办。也就是说,如果我有这样的数据(使用之前post的数据作为基础):
| SomeID | OtherID | Data | RelatedData |
+----------------+-------------+-----------+-------------+
| abcdef-..... | cdef123-... | 18,20,22 | xxx,,yyy |
| abcdef-..... | 4554a24-... | 17,19 | a,bb |
| 987654-..... | 12324a2-... | 13,19,20 | r,s,t |
并且想要 return 行如下:
| SomeID | OtherID | Data | RelatedData |
+----------------+-------------+------+-------------+
| abcdef-..... | cdef123-... | 18 | xxx |
| abcdef-..... | cdef123-... | 20 | |
| abcdef-..... | cdef123-... | 22 | yyy |
| abcdef-..... | 4554a24-... | 17 | a |
| abcdef-..... | 4554a24-... | 19 | bb |
| ... | ... | ... | ... |
我希望使用 STRING_SPLIT 因为它很简单,但我找不到让它工作的方法。这不起作用:
select OtherID, cs1.Value, cs2.Value
from yourtable
cross apply STRING_SPLIT (Data, ',') cs1
cross apply STRING_SPLIT (RelatedData, ',') cs2
有什么建议吗?
我同意有关此设计的评论。最好将数据标准化。
要使用 string_split()
执行此操作,您可以使用 row_number()
解决方法来处理序号,如下所示:
;with cs1 as (
select SomeId, OtherId, x.Value
, ItemNumber = row_number() over (partition by t.SomeId, t.OtherId order by (Select Null))
from t
cross apply string_split(Data,',') x
)
, cs2 as (
select SomeId, OtherId, x.Value
, ItemNumber = row_number() over (partition by t.SomeId, t.OtherId order by (Select Null))
from t
cross apply string_split(RelatedData,',') x
)
select cs1.SomeId, cs1.OtherId, cs1.Value, cs2.Value
from cs1
inner join cs2
on cs1.SomeId = cs2.SomeId
and cs1.OtherId = cs2.OtherId
and cs1.ItemNumber = cs2.ItemNumber
returns:
+--------------+-------------+-------+-------+
| SomeId | OtherId | Value | Value |
+--------------+-------------+-------+-------+
| 987654-..... | 12324a2-... | 13 | r |
| 987654-..... | 12324a2-... | 19 | s |
| 987654-..... | 12324a2-... | 20 | t |
| abcdef-..... | 4554a24-... | 17 | a |
| abcdef-..... | 4554a24-... | 19 | bb |
| abcdef-..... | cdef123-... | 18 | xxx |
| abcdef-..... | cdef123-... | 20 | |
| abcdef-..... | cdef123-... | 22 | yyy |
+--------------+-------------+-------+-------+
我认为使用包含序数的自定义函数更简单。例如,Jeff Moden 的定界拆分内联 table 值函数:
select SomeId, OtherId, cs1.Item, cs2.Item
from t
cross apply dbo.delimitedsplit8K(Data,',') cs1
cross apply dbo.delimitedsplit8K(RelatedData,',') cs2
where cs1.ItemNumber = cs2.ItemNumber
returns同样的结果。
拆分字符串参考:
- Tally OH! An Improved SQL 8K “CSV Splitter” Function - Jeff Moden
- Splitting Strings : A Follow-Up - Aaron Bertrand
- Split strings the right way – or the next best way - Aaron Bertrand
string_split()
in SQL Server 2016 : Follow-Up #1 - Aaron Bertrand
- Ordinal workaround for **
string_split()**
- Solomon Rutzky
之前有人问过 Turning a Comma Separated string into individual rows。这对一个专栏很有用,但我有一个扩展问题。如果我想拆分两个(或更多)相关列怎么办。也就是说,如果我有这样的数据(使用之前post的数据作为基础):
| SomeID | OtherID | Data | RelatedData |
+----------------+-------------+-----------+-------------+
| abcdef-..... | cdef123-... | 18,20,22 | xxx,,yyy |
| abcdef-..... | 4554a24-... | 17,19 | a,bb |
| 987654-..... | 12324a2-... | 13,19,20 | r,s,t |
并且想要 return 行如下:
| SomeID | OtherID | Data | RelatedData |
+----------------+-------------+------+-------------+
| abcdef-..... | cdef123-... | 18 | xxx |
| abcdef-..... | cdef123-... | 20 | |
| abcdef-..... | cdef123-... | 22 | yyy |
| abcdef-..... | 4554a24-... | 17 | a |
| abcdef-..... | 4554a24-... | 19 | bb |
| ... | ... | ... | ... |
我希望使用 STRING_SPLIT 因为它很简单,但我找不到让它工作的方法。这不起作用:
select OtherID, cs1.Value, cs2.Value
from yourtable
cross apply STRING_SPLIT (Data, ',') cs1
cross apply STRING_SPLIT (RelatedData, ',') cs2
有什么建议吗?
我同意有关此设计的评论。最好将数据标准化。
要使用 string_split()
执行此操作,您可以使用 row_number()
解决方法来处理序号,如下所示:
;with cs1 as (
select SomeId, OtherId, x.Value
, ItemNumber = row_number() over (partition by t.SomeId, t.OtherId order by (Select Null))
from t
cross apply string_split(Data,',') x
)
, cs2 as (
select SomeId, OtherId, x.Value
, ItemNumber = row_number() over (partition by t.SomeId, t.OtherId order by (Select Null))
from t
cross apply string_split(RelatedData,',') x
)
select cs1.SomeId, cs1.OtherId, cs1.Value, cs2.Value
from cs1
inner join cs2
on cs1.SomeId = cs2.SomeId
and cs1.OtherId = cs2.OtherId
and cs1.ItemNumber = cs2.ItemNumber
returns:
+--------------+-------------+-------+-------+
| SomeId | OtherId | Value | Value |
+--------------+-------------+-------+-------+
| 987654-..... | 12324a2-... | 13 | r |
| 987654-..... | 12324a2-... | 19 | s |
| 987654-..... | 12324a2-... | 20 | t |
| abcdef-..... | 4554a24-... | 17 | a |
| abcdef-..... | 4554a24-... | 19 | bb |
| abcdef-..... | cdef123-... | 18 | xxx |
| abcdef-..... | cdef123-... | 20 | |
| abcdef-..... | cdef123-... | 22 | yyy |
+--------------+-------------+-------+-------+
我认为使用包含序数的自定义函数更简单。例如,Jeff Moden 的定界拆分内联 table 值函数:
select SomeId, OtherId, cs1.Item, cs2.Item
from t
cross apply dbo.delimitedsplit8K(Data,',') cs1
cross apply dbo.delimitedsplit8K(RelatedData,',') cs2
where cs1.ItemNumber = cs2.ItemNumber
returns同样的结果。
拆分字符串参考:
- Tally OH! An Improved SQL 8K “CSV Splitter” Function - Jeff Moden
- Splitting Strings : A Follow-Up - Aaron Bertrand
- Split strings the right way – or the next best way - Aaron Bertrand
string_split()
in SQL Server 2016 : Follow-Up #1 - Aaron Bertrand- Ordinal workaround for **
string_split()**
- Solomon Rutzky