2014-12-19 3 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] 

Я пытаюсь для того чтобы достигнуть здесь заменить Count (1) с Count ([Extent2]. [ID]), поэтому в случае отсутствия записей, связанных с заказом, я хочу показать 0 вместо 1.

Может кто-нибудь помочь мне с обновлением запроса LINQ для достижения этого?

UPDATE:

заменить ниже будет возвращать результат за то, что я хотел, но это также превращает мой SQL запрос для выполнения медленнее ..

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

Вы можете попробовать 'Count = g.Select (х => x.id) .Count()' или даже добавить 'Distinct', если он не Работа. – MarcinJuraszek

+0

Привет, он не работает, так как у меня есть столбец id как в заказах, так и в таблице order_entries. Когда я добавил, что это не изменило какой-либо запрос, я думаю, что он думает, что идентификатор из таблицы заказов. – superted

ответ

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

Я твердо верю в это, что второй запрос может быть прописан в простейших образом с помощью группы заявления.

Вот полный 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;} 
    } 

} 
Смежные вопросы