2010-08-08 11 views
2

J'ai un tableau Employés avec des employés (disons que les champs importants sont ID int, Nom varchar (50)) et un tableau Zones avec zones de vente (ID int, EmployeeID int, USState char (2)).Requête SQL pour joindre des valeurs à partir de plusieurs enregistrements

Les valeurs d'échantillon sont:

Employees 
ID  Name 
1  Shoeman 
2  Smith 
3  Johnson 

Areas 
ID  EmployeeID  USState 
1  1    NY 
2  1    FL 
3  1    AR 
4  2    DC 
5  2    AR 
6  3    TX 

Quelqu'un peut-il me donner un indice à faire une requête SQL pour obtenir le jeu d'enregistrements de sortie de la manière suivante:

EmployeeID  USState 
1    NY FL AR 
2    DC AR 
3    TX 

plate-forme cible: SQL Server 2005

+0

Voir aussi: http://stackoverflow.com/questions/451415/simulating-group-concat-mysql-function-in-ms-sql-server-2005 –

Répondre

2

Cette opération est appelée GROUP_CONCAT dans MySQL mais SQL Server ne la prend pas en charge.

Dans SQL Server, vous pouvez simuler la même fonctionnalité à l'aide du hack FOR XML PATH. Une alternative consiste à utiliser un recursive CTE. Ceci est une solution moins hacky, mais il est aussi plus compliqué:

WITH qs(EmployeeID, USState, rn, cnt) AS 
(
    SELECT 
     EmployeeID, 
     USState, 
     ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY USState), 
     COUNT(*) OVER (PARTITION BY EmployeeID) 
    FROM Areas 
), 
t (EmployeeID, prodname, gc, rn, cnt) AS 
(
    SELECT EmployeeID, USState, CAST(USState AS NVARCHAR(MAX)), rn, cnt 
    FROM qs 
    WHERE rn = 1 
    UNION ALL 
    SELECT 
     qs.EmployeeID, qs.USState, 
     CAST(t.gc + ' ' + qs.USState AS NVARCHAR(MAX)), 
     qs.rn, qs.cnt 
    FROM t 
    JOIN qs ON qs.EmployeeID = t.EmployeeID 
      AND qs.rn = t.rn + 1 
) 
SELECT EmployeeID, gc AS USState 
FROM t 
WHERE rn = cnt 
ORDER BY EmployeeID 
OPTION (MAXRECURSION 0) 

Les deux méthodes donnent le résultat souhaité:

 
EmployeeID  USState 
1    NY FL AR 
2    DC AR 
3    TX 
+0

votre code 'hack' a fait l'affaire! Merci pour votre aide –

+0

J'aime le CTE, mais jusqu'à maintenant, aucun temps utilisé CTC récursif. Merci pour un exemple intéressant de ceci! – Oleg

1

Ceci est mon format de perfered d'utiliser une UDF (semble être beaucoup plus rapide aussi bien sur un grand DB)

CREATEFUNCTION dbo.StateList(@ID int) RETURNS varchar(max) 

AS 

DECLARE @out varchar(max); 

SET @out=''; -- comment this out to reutrn NULL if nothing found 

SELECT @[email protected]+USState+' ' -- operates like a loop assigning the values in sequence to the out variable. 

FROM AREAS 
WHERE [email protected] 
ORDER BY USState 

RETURN @out 

exemple de requête ...

SELECT Name, dbo.StateList(EmployeeID) 
FROM Employees 
Order BY Name 

De cette manière, vous créez un UDF pour chaque liste que vous souhaitez faire exploser de cette manière.