2017-08-24 1 views
2

Précédemment quelqu'un a posé des questions sur Turning a Comma Separated string into individual rows. Cela fonctionne très bien pour une colonne, mais j'ai une question d'extension. Que faire si je veux diviser deux (ou plusieurs) colonnes associées. Autrement dit, si j'ai des données comme celle-ci (en utilisant les données du poste précédent comme base):Transformation de chaînes séparées par des virgules en lignes individuelles avec plusieurs colonnes

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

et que vous voulez retourner les lignes comme les suivantes:

| SomeID   | OtherID  | Data | RelatedData | 
+----------------+-------------+------+-------------+ 
| abcdef-..... | cdef123-... | 18 | xxx   | 
| abcdef-..... | cdef123-... | 20 |    | 
| abcdef-..... | cdef123-... | 22 | yyy   | 
| abcdef-..... | 4554a24-... | 17 | a   | 
| abcdef-..... | 4554a24-... | 19 | bb   | 
| ...   | ...   | ... | ...   | 

J'espérais utiliser STRING_SPLIT en raison de sa simplicité, mais je ne peux pas trouver un moyen de le faire fonctionner. Cela ne fonctionne pas:

select OtherID, cs1.Value, cs2.Value 
from yourtable 
cross apply STRING_SPLIT (Data, ',') cs1 
cross apply STRING_SPLIT (RelatedData, ',') cs2 

Des suggestions?

+0

'ROW_NUMBER()', 'JOIN', puis' CROSS APPLY'. –

+3

Temps pour re-concevoir la base de données - c'est la vraie réponse. –

+0

Alternativement, si les gens ne peuvent pas être persuadés de normaliser leurs données, envisager JSON. Stocker ensemble des données reliées simplifierait grandement ces problèmes. Sauter à travers les colonnes "liées" est très gênant, peu importe comment vous le découpez. –

Répondre

4

Je suis d'accord avec les commentaires concernant ce modèle. Il vaudrait mieux normaliser vos données.

Pour ce faire avec string_split() vous pouvez utiliser la solution de contournement row_number() pour un ordinal comme ceci:

;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

retours:

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

Je pense qu'il est plus simple utiliser une fonction personnalisée qui inclut une ordi nal. Par exemple, la table en ligne divisée délimitée fonction d'une valeur par Jeff Moden:

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 

renvoie les mêmes résultats.


référence des chaînes de division:

+0

Cela a fonctionné comme un charme. J'ai essayé les deux, et fais comme la deuxième version car c'est beaucoup plus propre. Merci! – dmonder