SQL – Concaténation de valeurs lorsque le nombre d'éléments n'est pas connu

J'actualise actuellement mes connaissances en SQL et j'ai rencontré quelques difficultés avec la requête suivante.

Les exigences étaient:

Pour chaque fabricant, listr dans l'ordre alphabétique avec "/" comme délimiteur tous les types de produits qu'il produit.

Déduire: fabricant, list des types de produits

La solution suivante fonctionne réellement mais je ne comprends pas exactement comment ..

;with t1 as (select maker, type, DENSE_RANK() over(partition by maker order by type) rn from product ), tr(maker, type,lev) as (select distinct t1.maker, cast(t1.type as nvarchar) , 2 from t1 where t1.rn = 1 union all select t1.maker, cast(tr.type +'/'+t1.type as nvarchar), lev + 1 from t1 join tr on (t1.maker = tr.maker and t1.rn = tr.lev ) ) select maker, max(type) names from tr group by maker 

Ces sorties:

 1 | A | Laptop/PC/Printer 2 | B | Laptop/PC 3 | C | Laptop 4 | D | Printer 5 | E | PC/Printer 

* La deuxième colonne est le fabricant et la troisième est la list dynamicment concaténée des types.

Maintenant, je suis un peu confus sur la façon dont le lev se développe dynamicment .. Y at-il une sorte de boucle qui me manque ici? Pourquoi ça commence avec 2? Pourquoi ça ne marche pas sans le "casting"?

Je serais très reconnaissant si quelqu'un pouvait expliquer la logique derrière cette requête.

Merci beaucoup!

Ce que vous regardez est un CTE récursif, un CTE qui s'appelle lui-même. C'est ce que vous pensez être l'effet "en boucle". La récursion a mis un pli dans mon cerveau quand je l'ai regardé pour la première fois. Il est utile de regarder quelques exemples et d'en créer quelques-uns simples. Je ne suis toujours pas le meilleur, mais je vais mieux. J'ai ajouté quelques commentaires à votre code. J'espère que cela t'aides.

 ;WITH t1 AS ( SELECT maker, type, --Partition says each maker is a group so restart at 1 --Order by type is alphabetic --DENSE_RANK() means if there are two the of the same item, they get the same number DENSE_RANK() OVER (PARTITION BY maker ORDER BY type) rn FROM product ), --This is a recursive CTE meaning a CTE that calls itself(what is doing the "looping" tr (maker,type,lev) AS ( --Grab only the distinct items from your ranked table SELECT DISTINCT t1.maker, cast(t1.type AS NVARCHAR), 2 --This is the start of your recursive loop FROM t1 WHERE t1.rn = 1 UNION ALL --Recursively loop through you data, adding each ssortingng at the end with the '/' SELECT t1.maker, cast(tr.type + '/' + t1.type AS NVARCHAR), --Plus one to grab the next value lev + 1 FROM t1 INNER JOIN tr ON ( --Only match the same makers t1.maker = tr.maker --Match to the next value AND t1.rn = tr.lev ) ) --I think you know what this does SELECT maker, max(type) names FROM tr GROUP BY maker