Requête pour les identifiants séparés par des virgules avec des valeurs séparées par des virgules

J'ai 2 tables

Départements

ID Dept --------- 1 HR 2 Accts 3 IT 

Employé

 ID Name Depts ------------------- 1 Kevin 2,1 2 Michelle 1 3 Troy 1,3 4 Rheesa 2,3,1 

Je suis à la search d'une sortie comme celle-ci avec une requête SQL.

Dépôts des employés

 ID Name Depts ------------------------- 1 Kevin Accts,HR 2 Michelle HR 3 Troy HR,IT 4 Rheesa Accts,IT,HR 

J'ai essayé ce qui suit qui rejoint s avec depts mais les résultats dans une rangée pour chaque département seulement. Comment puis-je get les résultats ci-dessus en utilisant une requête?

 select name, depts, dept from employee CROSS APPLY dbo.split_list(employee.depts ,',') split inner join dbo.department on depts= split.value order by name 

 DECLARE @Departments TABLE ( ID INT PRIMARY KEY, Dept VARCHAR(32) NOT NULL UNIQUE ); DECLARE @Employees TABLE ( ID INT PRIMARY KEY, Name NVARCHAR(64) NOT NULL, Depts VARCHAR(255) NOT NULL ); INSERT @Departments VALUES (1,'HR'), (2,'Accts'), (3,'IT'); INSERT @Employees VALUES (1,'Kevin','2,1'), (2,'Michelle','1'), (3,'Troy','1,3'), (4,'Rheesa','2,3,1'); SELECT ID, Name, Depts = STUFF((SELECT ',' + d.Dept FROM @Departments AS d INNER JOIN @Employees AS ei ON ',' + ei.Depts + ',' LIKE '%,' + CONVERT(VARCHAR(12), d.id) + ',%' WHERE ei.ID = e.ID ORDER BY Dept FOR XML PATH, TYPE).value('.[1]', 'nvarchar(max)'), 1, 1, '') FROM @Employees AS e ORDER BY ID; 

Les résultats ne correspondent pas tout à fait aux résultats requirejs, car la command est déterministe (classée par nom de département):

 ID Name Depts ---- -------- ---- 1 Kevin Accts,HR 2 Michelle HR 3 Troy HR,IT 4 Rheesa Accts,HR,IT 

Si vous voulez les sortinger par leur apparence dans la list séparée par des virgules, changez simplement:

 ORDER BY Dept 

À:

 ORDER BY CHARINDEX( ',' + CONVERT(VARCHAR(12), d.id) + ',', ',' + ei.Depts + ',') 

Résultats:

 ID Name Depts ---- -------- ---- 1 Kevin Accts,HR 2 Michelle HR 3 Troy HR,IT 4 Rheesa Accts,IT,HR -- this is the only one affected as it turns out 

Cependant, en réalité, vous devriez normaliser votre database . C'est un cauchemar absolu.

Au-delà de la façon dont vous stockez vos données, laissez-moi essayer de vous aider.

Eh bien, vous posez beaucoup de questions ici. Tout d'abord, pour split datatables, vous pouvez le formater en XML et utiliser CROSS APPLY – truc que j'ai vu il y a quelques time et qui ne nécessitait pas de fonctions embeddedes.

Cela convertira votre string délimitée par des virgules à une list de strings. Vous pouvez ensuite utiliser FOR XML pour les reconstituer.

Donnez un coup de feu:

 SELECT E.Id, E.Name, STUFF( ( SELECT ',' + D.Department AS [text()] FROM ( SELECT A.[id], Split.a.value('.', 'VARCHAR(100)') AS DeptId FROM (SELECT [id], CAST ('<M>' + REPLACE(Depts, ',', '</M><M>') + '</M>' AS XML) AS Ssortingng FROM Employee ) AS A CROSS APPLY Ssortingng.nodes ('/M') AS Split(a)) A JOIN Departments D ON A.DeptId = D.Id WHERE E.Id = A.Id FOR XML PATH('') ), 1, 1, '') AS Departments FROM Employee E 

Et voici le violon SQL .

Bonne chance.

Vous pouvez également utiliser un CTE récursif pour split datatables, puis utiliser FOR XML PATH pour concaténer les lignes en une seule ligne:

 ;with cte (id, name, deptid, depts) as ( select id, name, cast(left(depts, charindex(',',depts+',')-1) as varchar(50)) deptid, stuff(depts, 1, charindex(',',depts+','), '') depts from employee union all select id, name, cast(left(depts, charindex(',',depts+',')-1) as varchar(50)) deptid, stuff(depts, 1, charindex(',',depts+','), '') depts from cte where depts > '' ) select e.id, e.name, stuff(( select distinct ', '+ d.dept from cte c inner join departments d on c.deptid = d.id where e.id = c.id for XML path('')),1,1,'') Depts from employee e 

Voir SQL Fiddle avec démo

Résultat:

 | ID | NAME | DEPTS | ---------------------------------- | 1 | Kevin | Accts, HR | | 2 | Michelle | HR | | 3 | Troy | HR, IT | | 4 | Rheesa | Accts, HR, IT | 

Vous pouvez également utiliser l'option avec la fonction de gestion dynamic sys.dm_fts_parser
Avant l'exécution du script, vous devez vérifier que le composant de text intégral est installé:

 SELECT FULLTEXTSERVICEPROPERTY ('IsFulltextInstalled') 

0 = Le text intégral n'est pas installé. 1 = Le text intégral est installé. NULL = Entrée non valide ou erreur.

Si 0 = Texte intégral n'est pas installé alors ce message vous est nécessaire Comment installer fulltext sur sql server 2008?

 SELECT b.ID, b.Name, STUFF(( SELECT ',' + d.Dept FROM Employees e JOIN Departments d ON d.ID IN( SELECT display_term FROM sys.dm_fts_parser('"' + e.Depts + '"', 1033, NULL, 0) WHERE display_term NOT LIKE 'nn%' ) WHERE b.ID = e.ID ORDER BY d.Dept FOR XML PATH('')), 1, 1, '') AS Depts FROM Employees b 

OU

 SELECT e.ID, e.Name, ( STUFF(( SELECT ',' + Dept FROM sys.dm_fts_parser('"' + e.Depts + '"', 1033, NULL, 0) p JOIN Departments d ON p.display_term = d.ID WHERE display_term NOT LIKE 'nn%' FOR XML PATH('')), 1, 1, '') ) AS Depts FROM Employees e 

Ecrivez une fonction pour split les valeurs séparées par des virgules. J'ai écrit dbo.split

select * from dbo.split ('1,2,3', ',') Renvoie comme – Données 1 2 3

 SELECT tact.ActivityID,CONVERT(NVARCHAR(20),tact.createddate,103) AS CallDate, ActivityOriginatedByPartyID , (ISNULL(p.firstname,'')+' '+ISNULL(p.lastname,'')) AS PartnerName, u.UserName AS PSTName, ccv.codevalue AS CallType **, ccv1.codevalue AS CallContext** ,tact.ActivityNote AS CallTrackerNote, (CONVERT(VARCHAR(20),tact.ActivityTimeSpend) + ' Min') AS CallDuration FROM txn_activity tact (NOLOCK) INNER JOIN TXN_Party p (NOLOCK) ON p.PartyID = tact.ActivityOriginatedByPartyID INNER JOIN TXN_User u (NOLOCK) ON u.userid = tact.createdby INNER JOIN CFG_CodeValue ccv (NOLOCK) ON ccv.codevalueid = tact.ActivityTypeID --INNER JOIN CFG_CodeValue ccv1 (NOLOCK) ON ccv1.codevalueid = tact.ActivityContext **CROSS APPLY dbo.split(tact.ActivityContext,',') split inner join dbo.CFG_CodeValue ccv1 (NOLOCK) ON ccv1.codevalueid = split.data**