2017-08-24 131 views
2

此前有人問起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 

有什麼建議嗎?

+0

'ROW_NUMBER()','JOIN',然後'CROSS APPLY'。 –

+3

重新設計數據庫的時間 - 這是真正的答案。 –

+0

或者,如果無法說服人們規範化數據,請考慮使用JSON。將相關數據存儲在一起至少可以大大簡化這些問題。無論你如何切片,跳過「相關」列是非常不方便的。 –

回答

4

我同意關於這種設計的意見。將數據標準化會更好。

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

我認爲這是簡單使用包含ordi的自定義函數最終。例如,分隔的分裂內嵌表值函數由Jeff模式N:

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 

返回相同的結果。


分割字符串參考:

+0

這工作就像一個魅力。我嘗試了兩種,並且喜歡第二個版本,因爲它更清潔。謝謝! – dmonder