2010-08-08 3 views
7

Использование Linq to Sql, как мне группировать следующие 2 таблицы.Linq - группа по нескольким таблицам

заказов Таблица:

CustomerID | Name |Date    
1   | order1 | 2010-01-01 
2   | order2 | 2010-01-01 
2   | order3 | 2010-04-01 

Calls Таблица:

CustomerID | Name |Date    
1   | call1 | 2010-01-01 
3   | call2 | 2010-06-01 
2   | call3 | 2010-05-01 

Я хочу, чтобы сгруппировать две таблицы по дате, Результат:

Date  | Orders | Calls 
2010-01-01 | 2  | 1 
2010-04-01 | 1  | 0 
2010-05-01 | 0  | 1 
2010-06-01 | 0  | 1 

я знаю, как сгруппировать одну таблицу,

from o in Orders   
group o by o.Date.Date into og 
select new {Date = og.Key,Orders= og.Count()}; 

Как я группа обоих? thx!

ответ

9

Поскольку обе таблицы имеют сходную структуру, я бы рекомендовал проецировать их в эквивалентную форму, а затем группировать по конкатенации этих двух наборов.

var orders = from o in Orders 
      select new { IsOrder = true, o.Date }; 
var calls = from c in Calls 
      select new { IsOrder = false, c.Date }; 

var result = from x in orders.Concat(calls)   
      group x by x.Date into og 
      select new {Date = og.Key, Orders= og.Count(o=>o.IsOrder), Calls = og.Count(c=>!c.IsTrue)}; 

Из-за ленивой природы Linq2Sql это может быть фактически сведено к одному запросу. В интересах производительности я бы удостоверился, что это не запрос из ада.

+0

Можете ли вы привести пример, пожалуйста? – dano

+0

thx! , я надеялся, что смогу использовать обычные команды linq/sql, я не думал о согласовании двух таблиц. вы бы сделали то же самое, если это был простой TSQL? – dano

+0

В TSQL я бы использовал полное внешнее соединение, но это нелегко в L2S, я надеюсь, что решение, которое я предоставил, проще, чем писать полное внешнее соединение. Просто выполните поиск SO, если вам нужна дополнительная информация о том, как использовать FOJ в Linq. –

1

Вы можете использовать метод Union:

var result = 
     (from c in Calls group c by c.Date into cg select new {Date = cg.Key, Calls = cg.Count(), Orders = 0}) 
     .Union(from o in Orders group o by o.Date into og select new {Date = og.Key, Calls = 0, Orders = og.Count()}) 
     .GroupBy(x => x.Date) 
     .Select(g => new {Date = g.Key, Calls = g.Max(r => r.Calls), Orders = g.Max(r => r.Orders)}); 

    foreach (var row in result) 
    { 
     Trace.WriteLine(row); 
    } 

Это очень похоже на SQL вы пишете (объединение двух таблиц, а затем внешний запрос, чтобы объединить результаты в ряд)

+0

thx Это действительно похоже на ответ «Йоханнес Рудольф». – dano

+0

Да, но это скорее приведет к одному выражению SQL. Лучше всего поставить их и посмотреть на отладчик :) –

+1

im get «Все запросы, объединенные с помощью оператора UNION, INTERSECT или EXCEPT, должны иметь равное количество выражений в своих целевых списках», подумайте, что если таблицы имеют разные даты, запрос будет потерпеть неудачу – dano

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