2010-09-03 4 views
3

J'essaie d'utiliser le T-SQL 'For Xml Path' pour générer une liste de valeurs séparées par des virgules à partir d'une colonne. Cela semble fonctionner, mais le problème est que je voudrais obtenir un compte des éléments dans la liste séparée par des virgules. Voici un exemple de code que je utilise pour générer la liste séparés par des virgules:Sql Pour Xml Path obtenir le nombre de nœuds

Create Table #List ([col] varchar) 

Insert Into #List Select '1'; 
Insert Into #List Select '2'; 
Insert Into #List Select '3' 

Select ',' + [col] From #List For Xml Path('') 

Cela donne les résultats 1,2,3 comme prévu, mais il n'y a pas moyen d'obtenir le nombre qu'il ya 3 articles . Toute tentative d'ajout d'un nombre va simplement l'ajouter au fichier XML. Je combiné ce code avec un cte pour obtenir le nombre:

With CTE As (
    Select 
     [col] 
    From 
     #List 
) 
Select 
    (Select ',' + [col] From #List For Xml Path('')) As [List], 
    Count(*) As [Count] 
From 
    CTE 

Y at-il un moyen plus facile/plus propre pour obtenir le nombre de nœuds sans utiliser un CTE? Il a été souligné que vous pouvez simplement dupliquer la clause from à l'intérieur du select interne et à l'extérieur, mais cela nécessite de garder les clauses from synchronisées. Je veux obtenir à la fois la liste et le compte, mais seulement la clause from une fois écrite.

Répondre

2

Que diriez-vous des données de dessin au lieu du CDT de la table temporaire?

With CTE As (
    Select 
     [col] 
    From 
     #List 
    -- Many joins 
    -- Complicated where clause 
) 
Select 
    (Select ',' + [col] From Cte For Xml Path('')) As [List], 
    Count(*) As [Count] 
From 
    CTE 

Cela vous permettra de conserver vos jointures et vos prédicats de recherche en un seul endroit.

+0

C'est en fait ce que j'ai fini par utiliser. Cependant, j'ai fini par devoir mettre le select compliqué dans une table temporaire avant d'utiliser le CTE. Quand je me suis joint au CTE, la performance a été terrible. Il a fallu environ 2 secondes pour que la requête à l'intérieur du CTE revienne, cependant, cela prendrait toute la requête avec les heures de roll-up de la liste des virgules. Cela a pris tellement de temps que je ne l'ai jamais laissé finir tout le chemin. Si je place le sélecteur complexe dans une table temporaire, la requête prendra une seconde à s'exécuter. La seule chose que je peux comprendre est que le select à l'intérieur du CTE était en cours de relance pour chaque itération ??? – user355930

1

Vous n'avez pas besoin du CTE vous pouvez utiliser l'approche sous-requête directement

SELECT 
     COUNT(*) AS [Count], 
     (SELECT ',' + [col] FROM #List FOR XML PATH('')) AS [List] 
FROM #List 
+0

Ceci est une solution acceptable, mais le problème est qu'il faut dupliquer la logique de deux fois. Si je tirais d'une déclaration qui avait 10 jointures, je devrais répéter les jointures à l'intérieur de la sous-sélection et dans la clause from. Je veux être en mesure d'avoir la logique de jointure écrite une fois et obtenir la liste des virgules et le nombre. Je vais modifier ma question. J'ai essayé de vous voter, mais je n'ai pas assez de rep. – user355930

Questions connexes