2014-12-19 120 views
2

我對LINQ查詢很感興趣,並且一直困惑於計算出正確的方法來獲取相關條目的計數。LINQ Left加入羣組並計數

我下面LINQ查詢和

var result = (from OR in orders 
       join OE in order_entries on OR.id equals OE.order_id into temp 
       from LOE in temp.DefaultIfEmpty() 
       group LOE by new {OR.user_id, OR.site } into g 
       select new { 
        col1 = g.Key.user_id, 
        col2 = g.Key.site, 
        count = g.Count() , 
        cost = g.Sum(oe => oe.cost) 
       } 
); 

這變成

SELECT 
    1 AS [C1], 
    [GroupBy1].[K1] AS [user_id], 
    [GroupBy1].[K2] AS [site], 
    [GroupBy1].[A1] AS [C2], 
    [GroupBy1].[A2] AS [C3] 
    FROM (SELECT 
     [Extent1].[user_id] AS [K1], 
     [Extent1].[site] AS [K2], 
     COUNT(1) AS [A1], 
     SUM([Extent2].[cost]) AS [A2] 
     FROM [dbo].[orders] AS [Extent1] 
     LEFT OUTER JOIN [dbo].[order_entries] AS [Extent2] ON [Extent1].[id] = [Extent2].[order_id] 
     GROUP BY [Extent1].[user_id], [Extent1].[site] 
    ) AS [GroupBy1] 

我想在這裏acheive是更換計數(1),計數([Extent2]。[ID] )因此,如果沒有與訂單相關的條目,我想顯示0而不是1.

有人可以幫助我更新LINQ查詢來實現這一目標嗎?

UPDATE:

下面替換將返回結果的是我想要的,但這也變成我的SQL查詢來執行慢..

g.Where(i => i.orders != null).Count(), 
+0

你可以試試'數= g.Select(X => x.id).Count之間的()'甚至加上'Distinct'如果不工作。 – MarcinJuraszek 2014-12-19 02:40:48

+0

嗨,它不工作,因爲我有訂單和order_entries表中的id列。當我補充說,它並沒有改變任何查詢,我認爲它認爲ID是從訂單表。 – superted 2014-12-19 03:00:11

回答

0

最簡單的方法是使用subqueries

var qry = from o in orders 
     select new { 
      oid = o.ID, 
      uid = o.UserId, 
      site = o.Site, 
      count = order_entries.Where(oe=>oe.OrderId == o.ID).Count(), 
      cost = order_entries.Where(oe=>oe.OrderId == o.ID).Sum(oe=>oe.Cost) 
      }; 

但是,如果您想要加入兩個數據集,請使用:

var qry = (from o in orders join oe in order_entries on o.ID equals oe.OrderId into grp 
     from g in grp.DefaultIfEmpty() 
     select new{ 
      oid = o.ID, 
      uid = o.UserId, 
      site = o.Site, 
      count = grp.Count(), 
      cost = grp.Sum(e=>e.Cost) 
      }).Distinct(); 

我堅信它是第二查詢可以在簡單的方式使用語句writen。

下面是一個完整LinqPad樣本:

void Main() 
{ 

    List<TOrder> orders = new List<TOrder>{ 
     new TOrder(1, 1, "Site1"), 
     new TOrder(2, 1, "Site1"), 
     new TOrder(3, 2, "Site2"), 
     new TOrder(4, 2, "Site2"), 
     new TOrder(5, 3, "Site3") 
     }; 

    List<TOrderEntry> order_entries = new List<TOrderEntry>{ 
     new TOrderEntry(1, 1, 5.5), 
     new TOrderEntry(2, 1, 6.2), 
     new TOrderEntry(3, 1, 4.9), 
     new TOrderEntry(4, 1, 55.15), 
     new TOrderEntry(5, 1, 0.97), 
     new TOrderEntry(6, 2, 2.23), 
     new TOrderEntry(7, 2, 95.44), 
     new TOrderEntry(8, 2, 3.88), 
     new TOrderEntry(9, 2, 7.77), 
     new TOrderEntry(10, 3, 25.23), 
     new TOrderEntry(11, 3, 31.13), 
     new TOrderEntry(12, 4, 41.14) 
     }; 

//  var qry = from o in orders 
//   select new { 
//    oid = o.ID, 
//    uid = o.UserId, 
//    site = o.Site, 
//    count = order_entries.Where(oe=>oe.OrderId == o.ID).Count(), 
//    cost = order_entries.Where(oe=>oe.OrderId == o.ID).Sum(oe=>oe.Cost) 
//    }; 
//  qry.Dump(); 

     var qry = (from o in orders join oe in order_entries on o.ID equals oe.OrderId into grp 
      from g in grp.DefaultIfEmpty() 
      //group g by g into ggg 
      select new{ 
       oid = o.ID, 
       uid = o.UserId, 
       site = o.Site, 
       count = grp.Count(), 
       cost = grp.Sum(e=>e.Cost) 
       }).Distinct(); 
     qry.Dump(); 
} 


// Define other methods and classes here 
class TOrder 
{ 
    private int iid =0; 
    private int uid =0; 
    private string ssite=string.Empty; 

    public TOrder(int _id, int _uid, string _site) 
    { 
     iid = _id; 
     uid = _uid; 
     ssite = _site; 
    } 

    public int ID 
    { 
     get{return iid;} 
     set{iid = value;} 
    } 

    public int UserId 
    { 
     get{return uid;} 
     set{uid = value;} 
    } 

    public string Site 
    { 
     get{return ssite;} 
     set{ssite = value;} 
    } 
} 


class TOrderEntry 
{ 
    private int iid = 0; 
    private int oid = 0; 
    private double dcost = .0; 

    public TOrderEntry(int _iid, int _oid, double _cost) 
    { 
     iid = _iid; 
     oid = _oid; 
     dcost = _cost; 
    } 

    public int EntryId 
    { 
     get{return iid;} 
     set{iid = value;} 
    } 

    public int OrderId 
    { 
     get{return oid;} 
     set{oid = value;} 
    } 

    public double Cost 
    { 
     get{return dcost;} 
     set{dcost = value;} 
    } 

}