【问题标题】:Turning related Comma Separated strings into individual rows with multiple columns将相关的逗号分隔字符串转换为具有多列的单独行
【发布时间】:2018-02-02 08:42:30
【问题描述】:

以前有人问过Turning a Comma Separated string into individual rows。这对一个专栏很有用,但我有一个扩展问题。如果我想拆分两个(或更多)相关列怎么办。也就是说,如果我有这样的数据(使用上一篇文章中的数据作为基础):

| 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       |

并且想要返回如下行:

| 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

有什么建议吗?

【问题讨论】:

  • ROW_NUMBER()JOIN,然后是CROSS APPLY
  • 是时候重新设计数据库了——这才是真正的答案。
  • 另外,如果不能说服人们规范化他们的数据,可以考虑 JSON。将相关数据存储在一起至少会大大简化这些问题。无论您如何切片,跨“相关”列都非常不方便。
  • 我正在尝试将数据从一种非常奇怪的格式(具有多值字段的 Unidata)移动到规范化数据库中。过渡并不容易。

标签: sql-server sql-server-2016


【解决方案1】:

我同意 cmets 对此设计的看法。将数据标准化会更好。

要使用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

返回:

+--------------+-------------+-------+-------+
|    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 的 delimited split inline table valued 函数:

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

返回相同的结果。


拆分字符串参考:

【讨论】:

  • 这就像一个魅力。我都试过了,并且喜欢第二个版本,因为它更干净。谢谢!
猜你喜欢
  • 2021-12-13
  • 2016-01-29
  • 2012-02-01
  • 2015-05-20
  • 2012-11-26
相关资源
最近更新 更多