2009-08-20 10 views
1

J'ai un beaucoup pour expédier beaucoup de relation de table:LINQ plusieurs à plusieurs jointure gauche Regroupement

CUS_Phone: tient son propre identifiant unique, l'identifiant cus de sa table parent, ainsi que les dates de titre de nom, etc. .. CUS_Phone_JCT: tient son propre identifiant unique, l'identifiant du CUS_Phone et l'id de CUS_Phone CUS_Phone: tient son propre identifiant unique, et le numéro de téléphone

ici, j'ai une requête de jointure pour récupérer tous les noms et numéros de téléphone des clients:

var q = from c in CUS_Contact 
    join cp in CUS_Phone_JCT on c.Id equals cp.Contact_Id into cp2 
    from cp3 in cp2.DefaultIfEmpty() 
    join p in CUS_Phone on cp3.Phone_Id equals p.Id into p2 
    from p3 in p2.DefaultIfEmpty() 
    where c.Cus_Id == 9120 
    select new 
      { 
       c.Id, 
       c.Cus_Id, 
       c.Namefirst, 
       c.Namemiddle, 
       c.Namelast, 
       cp3.Phone.Phone, 
       c.Title, 
       c.Dept, 
       c.Des, c.Datecreate, 
       c.Dateupdate, 
       c.Usr_idcreate, 
       c.Usr_idupdate 
      }; 

foreach(var v in q){ 
Console.WriteLine(v.Id + "-" + v.Namefirst + "-" + v.Phone); 
} 

Comment puis-je formuler la requête pour regrouper les numéros par client? Je veux voir des clients distincts avec une liste de numéros par client (IEnumerable List). Il existe un exemple similaire dans la requête LINQPad spanishOrders, mais ils regroupent les détails de la commande par commande. Je ne sais pas comment faire avec mon schéma. Merci!


EDIT: Voici le sql de la première émise réponse ...

-- Region Parameters 
DECLARE @p0 Int SET @p0 = 4 
-- EndRegion 
SELECT (
    SELECT [t8].[id] 
    FROM (
     SELECT TOP (1) [t6].[id] 
     FROM [CUS_Contact] AS [t6] 
     LEFT OUTER JOIN [CUS_Phone_JCT] AS [t7] ON [t6].[id] = [t7].[Contact_Id] 
     WHERE [t2].[id] = [t6].[id] 
     ) AS [t8] 
    ) AS [Id], (
    SELECT [t11].[Cus_Id] 
    FROM (
     SELECT TOP (1) [t9].[Cus_Id] 
     FROM [CUS_Contact] AS [t9] 
     LEFT OUTER JOIN [CUS_Phone_JCT] AS [t10] ON [t9].[id] = [t10].[Contact_Id] 
     WHERE [t2].[id] = [t9].[id] 
     ) AS [t11] 
    ) AS [Cus_Id], (
    SELECT [t14].[namefirst] 
    FROM (
     SELECT TOP (1) [t12].[namefirst] 
     FROM [CUS_Contact] AS [t12] 
     LEFT OUTER JOIN [CUS_Phone_JCT] AS [t13] ON [t12].[id] = [t13].[Contact_Id] 
     WHERE [t2].[id] = [t12].[id] 
     ) AS [t14] 
    ) AS [Namefirst], (
    SELECT [t17].[namemiddle] 
    FROM (
     SELECT TOP (1) [t15].[namemiddle] 
     FROM [CUS_Contact] AS [t15] 
     LEFT OUTER JOIN [CUS_Phone_JCT] AS [t16] ON [t15].[id] = [t16].[Contact_Id] 
     WHERE [t2].[id] = [t15].[id] 
     ) AS [t17] 
    ) AS [Namemiddle], (
    SELECT [t20].[namelast] 
    FROM (
     SELECT TOP (1) [t18].[namelast] 
     FROM [CUS_Contact] AS [t18] 
     LEFT OUTER JOIN [CUS_Phone_JCT] AS [t19] ON [t18].[id] = [t19].[Contact_Id] 
     WHERE [t2].[id] = [t18].[id] 
     ) AS [t20] 
    ) AS [Namelast], (
    SELECT [t23].[title] 
    FROM (
     SELECT TOP (1) [t21].[title] 
     FROM [CUS_Contact] AS [t21] 
     LEFT OUTER JOIN [CUS_Phone_JCT] AS [t22] ON [t21].[id] = [t22].[Contact_Id] 
     WHERE [t2].[id] = [t21].[id] 
     ) AS [t23] 
    ) AS [Title], (
    SELECT [t26].[dept] 
    FROM (
     SELECT TOP (1) [t24].[dept] 
     FROM [CUS_Contact] AS [t24] 
     LEFT OUTER JOIN [CUS_Phone_JCT] AS [t25] ON [t24].[id] = [t25].[Contact_Id] 
     WHERE [t2].[id] = [t24].[id] 
     ) AS [t26] 
    ) AS [Dept], (
    SELECT [t29].[des] 
    FROM (
     SELECT TOP (1) [t27].[des] 
     FROM [CUS_Contact] AS [t27] 
     LEFT OUTER JOIN [CUS_Phone_JCT] AS [t28] ON [t27].[id] = [t28].[Contact_Id] 
     WHERE [t2].[id] = [t27].[id] 
     ) AS [t29] 
    ) AS [Des], (
    SELECT [t32].[datecreate] 
    FROM (
     SELECT TOP (1) [t30].[datecreate] 
     FROM [CUS_Contact] AS [t30] 
     LEFT OUTER JOIN [CUS_Phone_JCT] AS [t31] ON [t30].[id] = [t31].[Contact_Id] 
     WHERE [t2].[id] = [t30].[id] 
     ) AS [t32] 
    ) AS [Datecreate], (
    SELECT [t35].[dateupdate] 
    FROM (
     SELECT TOP (1) [t33].[dateupdate] 
     FROM [CUS_Contact] AS [t33] 
     LEFT OUTER JOIN [CUS_Phone_JCT] AS [t34] ON [t33].[id] = [t34].[Contact_Id] 
     WHERE [t2].[id] = [t33].[id] 
     ) AS [t35] 
    ) AS [Dateupdate], (
    SELECT [t38].[usr_idcreate] 
    FROM (
     SELECT TOP (1) [t36].[usr_idcreate] 
     FROM [CUS_Contact] AS [t36] 
     LEFT OUTER JOIN [CUS_Phone_JCT] AS [t37] ON [t36].[id] = [t37].[Contact_Id] 
     WHERE [t2].[id] = [t36].[id] 
     ) AS [t38] 
    ) AS [Usr_idcreate], (
    SELECT [t41].[usr_idupdate] 
    FROM (
     SELECT TOP (1) [t39].[usr_idupdate] 
     FROM [CUS_Contact] AS [t39] 
     LEFT OUTER JOIN [CUS_Phone_JCT] AS [t40] ON [t39].[id] = [t40].[Contact_Id] 
     WHERE [t2].[id] = [t39].[id] 
     ) AS [t41] 
    ) AS [Usr_idupdate], [t2].[id] AS [id2] 
FROM (
    SELECT [t0].[id] 
    FROM [CUS_Contact] AS [t0] 
    LEFT OUTER JOIN [CUS_Phone_JCT] AS [t1] ON [t0].[id] = [t1].[Contact_Id] 
    GROUP BY [t0].[id] 
    ) AS [t2] 
WHERE ((
    SELECT [t5].[Cus_Id] 
    FROM (
     SELECT TOP (1) [t3].[Cus_Id] 
     FROM [CUS_Contact] AS [t3] 
     LEFT OUTER JOIN [CUS_Phone_JCT] AS [t4] ON [t3].[id] = [t4].[Contact_Id] 
     WHERE [t2].[id] = [t3].[id] 
     ) AS [t5] 
    )) = @p0 
GO 

-- Region Parameters 
DECLARE @x1 Int SET @x1 = 9327 
-- EndRegion 
SELECT [t2].[phone] AS [value] 
FROM [CUS_Contact] AS [t0] 
LEFT OUTER JOIN [CUS_Phone_JCT] AS [t1] ON [t0].[id] = [t1].[Contact_Id] 
LEFT OUTER JOIN [CUS_Phone] AS [t2] ON [t2].[id] = [t1].[Phone_Id] 
WHERE @x1 = [t0].[id] 
GO 
-- Region Parameters 
DECLARE @x1 Int SET @x1 = 9328 
-- EndRegion 
SELECT [t2].[phone] AS [value] 
FROM [CUS_Contact] AS [t0] 
LEFT OUTER JOIN [CUS_Phone_JCT] AS [t1] ON [t0].[id] = [t1].[Contact_Id] 
LEFT OUTER JOIN [CUS_Phone] AS [t2] ON [t2].[id] = [t1].[Phone_Id] 
WHERE @x1 = [t0].[id] 

Répondre

3

Je suis un peu confus par votre utilisation de cp3.Phone.Phone en plus de votre join contre CUS_Phone, donc je suis En supposant que le premier signifie que vous n'avez pas besoin de ce dernier. Sinon, il suffit de basculer en p3 pour cp3 dans le join et d'ajuster le g.Select() en conséquence.

Cela dit, vous devriez être en mesure de simplement groupe sur l'ID de contact:

var q = from c in CUS_Contact 
     join cp in CUS_Phone_JCT on c.Id equals cp.Contact_Id into cp2 
     from cp3 in cp2.DefaultIfEmpty() 
     group new { c, cp3.Phone.Phone } by c.Id into g 
     let c = g.First().c 
     select new { 
         c.Id, 
         c.Cus_Id, 
         c.Namefirst, 
         c.Namemiddle, 
         c.Namelast, 
         Phones = g.Select(x => x.Phone) 
         c.Title, 
         c.Dept, 
         c.Des, c.Datecreate, 
         c.Dateupdate, 
         c.Usr_idcreate, 
         c.Usr_idupdate 
        }; 

foreach(var v in q) { 
    Console.WriteLine(v.Id + "-" + v.Namefirst); 
    foreach(var p in v.Phones) { 
     Console.WriteLine(" -" + p); 
    } 
} 

Quelques coups de feu dans l'obscurité pour améliorer les performances:

var q = from c in CUS_Contact 
     join cp in CUS_Phone_JCT on c.Id equals cp.Contact_Id into cp2 
     from cp3 in cp2.DefaultIfEmpty() 
     group new { c, cp3.Phone.Phone } by c.Id into g 
     let c = g.First().c 
     select new { 
         c.Id, 
         c.Cus_Id, 
         c.Namefirst, 
         c.Namemiddle, 
         c.Namelast, 
         Phones = g.Select(x => x.Phone) 
         c.Title, 
         c.Dept, 
         c.Des, c.Datecreate, 
         c.Dateupdate, 
         c.Usr_idcreate, 
         c.Usr_idupdate 
        }; 

Vous pouvez également essayer regroupement par une clé composite (avec tous vos champs c) au lieu de c.Id:

 group cp3.Phone.Phone 
      by new { c.Id, c.Cus_Id, c.Namefirst, ETC } into g 
     let c = g.Key 
     select new { 
         ... 
         Phones = g.Select(p => p), 
         ... 
        } 

Mise à jour: Modifiez l'exemple de clé composite pour grouper uniquement la valeur Téléphone, car tout ce dont vous avez besoin doit figurer dans la clé.


Mise à jour 2: Vous pourriez être en mesure de simplifier les choses un peu en intégrant une sous-requête:

var q = from c in CUS_Contact 
     select new { 
         c.Id, 
         c.Cus_Id, 
         c.Namefirst, 
         c.Namemiddle, 
         c.Namelast, 
         Phones = (from cp in CUS_Phone_JCT 
           where c.Id == cp.Contact_Id 
           select cp.Phone.Phone), 
         c.Title, 
         c.Dept, 
         c.Des, c.Datecreate, 
         c.Dateupdate, 
         c.Usr_idcreate, 
         c.Usr_idupdate 
        }; 
+0

Je ne suis pas sûr de la Phone.Phone soit. Cela afficherait le nom de la table "CUS_Phone" à moins que j'ajoute le second. La requête fonctionne bien, sauf que cela prend presque 4 secondes par rapport à la précédente qui ne prend que moins d'un dixième de seconde. Des idées? – RyanOC

+0

A quoi ressemble le SQL généré? – dahlbyk

+0

C'est trop grand pour entrer ici. La limite de 600 caractères et son environ 4000. – RyanOC

Questions connexes