Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Je veux faire group_concat dans SQL Server

Pour vous donner une illustration de la jointure (dans ce cas, une auto-jointure, mais toutes les jointures fonctionnent) et de l'utilisation de STUFF pour cela. Remarquez la clause WHERE à l'intérieur de STUFF. C'est ce qui relie l'enregistrement aux valeurs correctes.

declare @test table
(
email varchar(50),
address varchar(50)
)

insert into @test VALUES
('[email protected]','A123A'),  
('[email protected]','AB263'),   
('[email protected]','45632A'),   
('[email protected]','78YU'),
('[email protected]','6543D')

SELECT DISTINCT 
       email,
       Stuff((SELECT ', ' + address  
              FROM   @test t2 
              WHERE  t2.email  = t1.email  
              FOR XML PATH('')), 1, 2, '') Address
FROM   @test t1  

Modifier

OK donc ce que vous voulez (ce que vous voulez vraiment, vraiment) est :

declare @customers table
(
emailaddress varchar(50),
customerid int
)

insert into @customers VALUES
('[email protected]',1),  
('[email protected]',2)   

declare @orders table
(
orderid int,
customerid int,
orderdate date
)

insert into @orders VALUES
(1, 1, '2017-06-02'),
(2, 1, '2017-06-05'),
(3, 1, '2017-07-13'),
(4, 2, '2017-06-13')

declare @orderdetails table
(
id int,
orderid int,
productcode varchar(10)
)

insert into @orderdetails VALUES
(1, 1, 'apple pie'),
(2, 1, 'bread'),
(3, 2, 'custard'),
(4, 2, 'orange'),
(5, 3, 'orange'),
(6, 4, 'orange')

SELECT DISTINCT c.EmailAddress, productcode=
STUFF((SELECT ',' + odc.productcode FROM 
(SELECT DISTINCT emailaddress,productcode FROM 
@orders o2 inner join @orderdetails od2 on
o2.orderid = od2.orderid
inner join @customers c2 ON c2.customerid = o2.customerid) odc 
WHERE odc.emailaddress=c.emailaddress 
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
FROM @OrderDetails od 
JOIN @Orders o ON od.OrderID = o.OrderID 
JOIN @Customers c ON c.CustomerID=o.CustomerID 
WHERE o.OrderDate BETWEEN '2016-01-01' AND getdate()

Remarquez le changement ici. Le SELECT dans le STUFF provient maintenant d'une sous-requête, de sorte que vous pouvez regrouper par EmailAddress.

Explication supplémentaire

Votre but est d'avoir une concaténation de codes produits regroupés par client (représenté par adresse email). Le problème est que les codes de produit sont dans la table des détails de la commande et que l'adresse e-mail est dans la table des clients, mais il n'y a pas de champ qui relie les deux. La table des clients a une relation un à plusieurs avec la table des commandes et la table des commandes a une relation un à plusieurs avec la table des détails de la commande. C'est un niveau d'abstraction de trop. Nous devons donc donner un coup de main à la base de données en fournissant un lien direct entre le code produit et l'adresse e-mail. C'est ce que nous faisons via la sous-requête. J'espère que cela vous éclaire davantage.