Hier ist eine Möglichkeit.
Theoretisch kann es mit bis zu 20 Tags pro Produkt umgehen (begrenzt durch die Größe der Zahlentabelle). Ich habe mich aber nicht darum gekümmert, das zu versuchen. Auf meinem Desktop dauerte es ungefähr 30 Sekunden, um die 65.535 Ergebnisse für ein einzelnes Produkt mit 16 Tags zu erhalten. Hoffentlich wird Ihre tatsächliche Anzahl von Tags pro Produkt viel geringer sein!
IF OBJECT_ID('tempdb..#Nums') IS NULL
BEGIN
CREATE TABLE #Nums
(
i int primary key
)
;WITH
L0 AS (SELECT 1 AS c UNION ALL SELECT 1),
L1 AS (SELECT 1 AS c FROM L0 A CROSS JOIN L0 B),
L2 AS (SELECT 1 AS c FROM L1 A CROSS JOIN L1 B),
L3 AS (SELECT 1 AS c FROM L2 A CROSS JOIN L2 B),
L4 AS (SELECT 1 AS c FROM L3 A CROSS JOIN L3 B),
L5 AS (SELECT 1 AS c FROM L4 A CROSS JOIN L4 B),
Nums AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS i FROM L5)
INSERT INTO #Nums
SELECT TOP 1048576 i FROM Nums;
END
;with ProductTags As
(
SELECT 1 ProductId,'Leather' AS Tag UNION ALL
SELECT 1, 'Watch' UNION ALL
SELECT 2, 'Red' UNION ALL
SELECT 2, 'Necklace' UNION ALL
SELECT 2, 'Pearl'
), NumberedTags AS
(
SELECT
ProductId,Tag,
ROW_NUMBER() OVER (PARTITION BY ProductId ORDER BY Tag) rn,
COUNT(*) OVER (PARTITION BY ProductId) cn
FROM ProductTags
),
GroupedTags As
(
SELECT ProductId,Tag,i
FROM NumberedTags
JOIN #Nums on
#Nums.i < POWER ( 2 ,cn)
and #Nums.i & POWER ( 2 ,rn-1) > 0
)
SELECT ProductId,
STUFF((SELECT CAST(', ' + Tag AS VARCHAR(MAX))
FROM GroupedTags g2
WHERE g1.ProductId = g2.ProductId and g1.i = g2.i
ORDER BY Tag
FOR XML PATH ('')),1,1,'') AS Tags
FROM GroupedTags g1
GROUP BY ProductId, i
ORDER BY ProductId, i
Rückgabe
ProductId Tags
----------- ------------------------------
1 Leather
1 Watch
1 Leather, Watch
2 Necklace
2 Pearl
2 Necklace, Pearl
2 Red
2 Necklace, Red
2 Pearl, Red
2 Necklace, Pearl, Red