将相关的逗号分隔字符串转换为具有多列的单独行

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

dbfiddle.uk demo

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同样的结果。


拆分字符串参考: