2009-08-20 67 views
1

我有一個多對多的關係表船:LINQ多對多左連接分組

CUS_Phone:擁有自己唯一的ID,從它的父表CUS ID以及姓名職務日期等。 .. CUS_Phone_JCT:擁有自己的唯一ID,從CUS_Phone ID和從CUS_Phone CUS_Phone的ID:擁有自己獨特的ID和手機號碼

在這裏,我有一個連接查詢檢索所有客戶的姓名和電話號碼:

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); 
} 

我該如何去制定查詢來對每個客戶的數量進行分組?我想查看不同客戶的每個客戶的數字列表(IEnumerable List)。 Theres在LINQPad spanishOrders查詢中有一個類似的例子,但是他們將每個訂單的訂單細節分組。我不知道如何用我的模式做到這一點。謝謝!


編輯:下面是從第一個答案輸出的SQL ...

-- 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] 

回答

3

我有點貴,除了使用cp3.Phone.Phone迷惑你joinCUS_Phone,所以我假設前者意味着你不需要後者。否則,只需在join中切入p3,cp3並相應地調整g.Select()

這就是說,你應該能夠簡單地組上的接觸ID:

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); 
    } 
} 

在黑暗中的幾個鏡頭,以提高性能:

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 
        }; 

您也可以嘗試通過組合鍵(使用所有c字段)來代替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), 
         ... 
        } 

更新:調整了複合鍵示例只分組電話值,因爲你需要的一切都應該在關鍵。


更新2:您可能能夠通過嵌入一個子查詢頗有幾分把事情簡單化:

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

林不知道有關Phone.Phone無論是。它會輸出表名「CUS_Phone」,除非我添加第二個。查詢的效果很好,除了需要幾乎4秒的時間,與以前相比,只需要不到十分之一秒。有任何想法嗎? – RyanOC 2009-08-20 17:16:10

+0

生成的SQL看起來像什麼? – dahlbyk 2009-08-20 17:44:03

+0

它太大,無法進入這裏。 600個字符的限制和約4000. – RyanOC 2009-08-20 18:11:47