0
votes

Split chaîne de longueur variable, délimiteurs variables

Lire la question posée ici , mais le mien est un peu plus compliqué.

J'ai une chaîne variable de longueur, et le délimiteur peut parfois être deux tirets, ou parfois, il ne peut être qu'un. Disons dans ma table que les données que je veux sortir sont stockées dans une seule colonne comme celle-ci: xxx

mais je veux émettre la chaîne de données de cette seule colonne dans Trois colonnes distinctes telles que ceci: xxx

espérant que les échantillons que j'ai trouvés sur Google semblent être plus simples que cela.


6 commentaires

Emplacement - Catégorie - Sous-catégorie Toujours la commande?


Pour les sortir où dans quelle langue?


@squillman Oui, ce sera toujours dans cet ordre. Il y aura toujours un lieu et une catégorie, mais la sous-catégorie est facultative et peut parfois être nulle. En outre, "zoo" n'est qu'un exemple de l'emplacement; L'emplacement peut être une longueur variable jusqu'à 255 caractères. Même avec la catégorie et la sous-catégorie.


@JQsoft C'est le résultat d'une requête SQL où le nom de la colonne dans la table est la catégorie.


De quel niveau de compatibilité est votre base de données?


Lorsque vous dites "Le délimiteur peut parfois être deux tirets", voulez-vous dire 'zoo - les invités' serait 'zoo' , "invités" plutôt que 'zoo' , null , "invités" ?


4 Réponses :


0
votes

peu de hack, mais cela fonctionne:

DECLARE @t TABLE (Category VARCHAR(255))

INSERT @t (Category)
VALUES ('Zoo - Animals - Lions'),('Zoo - Personnel'),('Zoo - Operating Costs - Power / Cooling')

;WITH split_vals AS (
    SELECT Category AS Cat,TRIM(Value) AS Value,ROW_NUMBER() OVER (PARTITION BY Category ORDER BY Category) AS RowNum
    FROM @t
    CROSS APPLY STRING_SPLIT(Category,'-')
), cols AS (
    SELECT
        Cat,
        CASE WHEN RowNum = 1 THEN Value END AS Location,
        CASE WHEN RowNum = 2 THEN Value END AS Category,
        CASE WHEN RowNum = 3 THEN Value END AS [Sub-Category]
    FROM split_vals
)
SELECT STRING_AGG(Location, '') AS Location,
       STRING_AGG(Category, '') AS Category,
       STRING_AGG([Sub-Category], '') AS [Sub-Category]
FROM cols
GROUP BY Cat;


8 commentaires

Obtenir ceci: "Trim" n'est pas un nom de fonction intégré reconnu. 'String_agg' n'est pas un nom de fonction intégré reconnu.


Et vous utilisez SQL 2017? Quel niveau de compatibilité est votre base de données?


110 ... Je n'ai aucun contrôle sur cela, je suis dans l'environnement d'entreprise.


OY ... 110 est la compatibilité SQL 2012. Vous devriez discuter avec votre DBA.


@squillman string_split () n'est pas garanti de renvoyer les fragments dans le même ordre qu'ils ont été transmis. Cela pourrait fonctionner dans tous les tests internes, passer toute validation et rompre toujours en production (avec des erreurs absolument idiotes, qui vous conduisent folle). Je viens de passer une réponse avec un séparateur de position et de sécurité à l'aide de Json (mais cela ne fonctionnera pas avec la compatibilité 110 non plus :-()


@Shnugo ahhh, ouais je viens de confirmer cela. Je ne l'ai jamais vu faire autrement, mais je n'ai pas non plus lu la DOC suffisamment (ni la peine de vérifier). Mais tu as absolument raison. Je suis vraiment content que vous ayez signalé cela à moi!


@squillman Pour être honnête: Je pense que le développement ne pensait pas à cela du tout ... string_split () est de peu ou pas d'utilisation sans une deuxième colonne pour la position de l'élément. Et personne ne gênait de penser à cela. Autant que je sache, l'indice de l'ordre de tri (dans les documents) a été ajouté plus tard, quand ils ont trouvé, que dans un contexte plus important (en raison du parallélisme?) Cela peut casser. Cependant, nous pouvons utiliser Json, qui est vraiment rapide heureusement.


@Shnugo Ouais, je suis d'accord avec ça. Aimer la solution JSON. J'utilise Json partout dans nos applications, même remplacé d'autres choses (comme des paramètres de table) en raison de la rapidité avec laquelle il est rapide. N'avait pas pensé à l'utiliser juste pour le positionnement. Bon produit.



2
votes

Voici une solution qui utilise uniquement des fonctions de chaîne: xxx

Démo sur DB Fiddle : xxx


1 commentaires

Merci, c'est la route qui va probablement aller, mais je reçois des résultats incohérents. Parfois, les données se séparent bien, quelque chose que ce n'est pas et je ne sais pas pourquoi.



2
votes

Vous pouvez également utiliser un séparateur de chaîne. Voici un excellent qui fonctionne avec votre version. Delimitedsplit8k

Maintenant, nous avons besoin de quelques données d'échantillonnage. xxx

maintenant que nous avons une fonction et des échantillons de données, le code pour cela est assez agréable et Tandy. xxx

et cela retournera: xxx


3 commentaires

Malheureusement, cela ne semble pas fonctionner avec ma base de données, probablement parce que c'est 2012, même s'il est écrit 2017. Le contrôle de la DBAS qui basé sur la gouvernance d'entreprise.


Avez-vous lu l'article lié? Vous devez avoir la fonction délimitedsplit8k. Et oui, cela fonctionne tout à fait avec 2012, fonctionne aussi loin que SQL Server 2005 lorsqu'ils ont d'abord introduit des fonctions de CTES et de valeurs de table.


Heureusement, j'ai pu créer la fonction et ça marche un régal! Merci beaucoup.



1
votes

Vous avez marqué cela avec [SQL-Server-2017] . Cela signifie que vous pouvez utiliser JSON-SUPPORT (cela a été introduit avec V2016).

Actuellement JSON est la meilleure approche intégrée pour la scission de la chaîne de position et de sécurité:

une maquette, pour simuler votre problème xxx

- la requête xxx

Le résultat (pourrait avoir besoin Quelques couper () ING) xxx

L'idée en bref:

Nous utilisons des opérations de chaîne simples pour transformer votre chaîne dans un tableau JSON: xxx

maintenant, nous pouvons utiliser openjson () avec un avec -clause pour ramener chacun fragment par sa position avec un type fixe.


1 commentaires

Oui, je l'ai marqué 2017 et n'aurait probablement pas dû émettre que le niveau de compatibilité est défini sur 110.