Le tableau est:
+----+------+
| Id | Name |
+----+------+
| 1 | aaa |
| 1 | bbb |
| 1 | ccc |
| 1 | ddd |
| 1 | eee |
+----+------+
Sortie requise:
+----+---------------------+
| Id | abc |
+----+---------------------+
| 1 | aaa,bbb,ccc,ddd,eee |
+----+---------------------+
Requete:
SELECT ID,
abc = STUFF(
(SELECT ',' + name FROM temp1 FOR XML PATH ('')), 1, 1, ''
)
FROM temp1 GROUP BY id
Cette requête fonctionne correctement. Mais j'ai juste besoin d'expliquer comment cela fonctionne ou existe-t-il un autre moyen ou court pour le faire.
Je suis très confus de comprendre cela.
sql
sql-server
database
Puneet Chawla
la source
la source
ID
est unique dans une table différente d'entités différentes, et cette table stocke les choses qui leur appartiennent.Réponses:
Voici comment cela fonctionne:
1. Obtenez la chaîne d'élément XML avec FOR XML
L'ajout de FOR XML PATH à la fin d'une requête vous permet de générer les résultats de la requête en tant qu'éléments XML, avec le nom de l'élément contenu dans l'argument PATH. Par exemple, si nous devions exécuter l'instruction suivante:
En passant une chaîne vide (FOR XML PATH ('')), nous obtenons ce qui suit à la place:
2. Supprimer la virgule principale avec STUFF
L'instruction STUFF "bourre" littéralement une chaîne dans une autre, en remplaçant les caractères de la première chaîne. Nous l'utilisons cependant simplement pour supprimer le premier caractère de la liste de valeurs résultante.
Les paramètres de
STUFF
sont:On se retrouve donc avec:
3. Rejoignez id pour obtenir la liste complète
Ensuite, nous venons de joindre cela sur la liste des identifiants dans la table temporaire, pour obtenir une liste des identifiants avec le nom:
Et nous avons notre résultat:
J'espère que cela t'aides!
la source
LISTAGG
égard en introduisant une fonction dans Oracle 11gR2. Je manque cette fonctionnalité les jours où je dois l'utiliser à la place. techonthenet.com/oracle/functions/listagg.phplist
fonction depuis des décennies. Malheureusement, Microsoft a basé SQLServer sur ASE de Sybase à la place, et n'a jamais pris la peine d'utiliser une fonction de liste jusqu'à l'année dernière. Je suis d'accord - c'est ahurissant. Et puis ils le font, ils l'appellentstring_agg
. J'aurais pensé quelist
c'était assez évident.Cet article couvre différentes façons de concaténer des chaînes dans SQL, y compris une version améliorée de votre code qui ne code pas XML les valeurs concaténées.
Pour comprendre ce qui se passe, commencez par la requête interne:
Parce que vous spécifiez
FOR XML
, vous obtiendrez une seule ligne contenant un fragment XML représentant toutes les lignes.Étant donné que vous n'avez pas spécifié d'alias de colonne pour la première colonne, chaque ligne sera encapsulée dans un élément XML avec le nom spécifié entre crochets après le
FOR XML PATH
. Par exemple, si vous l'aviezFOR XML PATH ('X')
, vous obtiendrez un document XML qui ressemblerait à:Mais, puisque vous n'avez pas spécifié de nom d'élément, vous obtenez simplement une liste de valeurs:
le
.value('.', 'varchar(max)')
récupère simplement la valeur du fragment XML résultant, sans encoder XML aucun caractère "spécial". Vous avez maintenant une chaîne qui ressemble à:le
STUFF
fonction supprime ensuite la virgule de tête, vous donnant un résultat final qui ressemble à:Cela semble assez déroutant à première vue, mais il a tendance à fonctionner assez bien par rapport à certaines des autres options.
la source
TYPE
directive indique à SQL de renvoyer les données en utilisant lexml
type. Sans cela, les données sont renvoyées sous forme de fichiernvarchar(max)
. Il est utilisé ici pour éviter les problèmes d'encodage XML s'il y a des caractères spéciaux dans laname
colonne.TYPE
et.value('.', 'varchar(max)')
, vous pouvez vous retrouver avec des entités codées XML dans le résultat.Le mode PATH est utilisé pour générer du XML à partir d'une requête SELECT
La sortie est un XML centré sur l'élément où chaque valeur de colonne de l'ensemble de lignes résultant est encapsulée dans un élément de ligne. Étant donné que la clause SELECT ne spécifie aucun alias pour les noms de colonne, les noms d'élément enfant générés sont les mêmes que les noms de colonne correspondants dans la clause SELECT.
Pour chaque ligne de l'ensemble de lignes, une balise est ajoutée.
Pour l'étape 2: si vous spécifiez une chaîne de longueur nulle, l'élément d'habillage n'est pas produit.
À l'étape 4, nous concaténons les valeurs.
À l'étape 6, nous regroupons la date par ID.
STUFF (source_string, start, length, add_string) Paramètres ou arguments source_string La chaîne source à modifier. start La position dans la chaîne_source pour supprimer les caractères de longueur, puis insérer la chaîne add_string. longueur Le nombre de caractères à supprimer de chaîne_source. add_string La séquence de caractères à insérer dans la source_string à la position de départ.
la source
','
colonne as spécifiée, combinée au('')
chemin après XML, provoque la concaténationSELECT 'a' FROM some_table FOR XML PATH('')
produira:'aaaaaaa'
. Mais si le nom de la colonne sera spécifié:SELECT 'a' AS Col FROM some_table FOR XML PATH('')
vous obtenez le résultat:<Col>a</Col><Col>a</Col><Col>a</Col>
Il existe de toutes nouvelles fonctionnalités dans Azure SQL Database et SQL Server (à partir de 2017) pour gérer ce scénario exact. Je crois que cela servirait de méthode officielle native pour ce que vous essayez d'accomplir avec la méthode XML / STUFF. Exemple:
STRING_AGG - https://msdn.microsoft.com/en-us/library/mt790580.aspx
EDIT: Lorsque j'ai initialement publié cela, j'ai fait mention de SQL Server 2016 car je pensais l'avoir vu sur une fonctionnalité potentielle qui devait être incluse. Soit je m'en suis souvenu incorrectement, soit quelque chose a changé, merci pour la modification suggérée corrigeant la version. En outre, assez impressionné et n'était pas pleinement au courant du processus d'examen en plusieurs étapes qui m'a simplement amené à une option finale.
la source
Dans
for xml path
, si nous définissons une valeur comme celle-[ for xml path('ENVLOPE') ]
ci, ces balises seront ajoutées à chaque ligne:la source
Ici, dans la requête ci-dessus, la fonction STUFF est utilisée pour simplement supprimer la première virgule
(,)
de la chaîne xml générée,(,aaa,bbb,ccc,ddd,eee)
elle deviendra alors(aaa,bbb,ccc,ddd,eee)
.Et
FOR XML PATH('')
convertit simplement les données de colonne en(,aaa,bbb,ccc,ddd,eee)
chaîne, mais dans PATH, nous transmettons '' afin qu'il ne crée pas de balise XML.Et à la fin, nous avons regroupé les enregistrements en utilisant colonne ID .
la source
J'ai fait le débogage et j'ai finalement renvoyé ma requête "bourrée" comme d'habitude.
Simplement
me donne le contenu de la table à écrire dans une table de journal à partir d'un déclencheur que je débogue.
la source
la source
STUFF ((SELECT distinct ',' + CAST (T.ID) FROM Table T où T.ID = 1 FOR XML PATH ('')), 1,1, '') AS Name
la source
Im utilisant fréquemment la clause where
la source