2010-08-08 84 views
7

Usando Linq a Sql cómo agrupo las 2 tablas siguientes.Linq - Agrupar por varias tablas

Órdenes Tabla:

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

llamadas Tabla:

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

quiero agrupar las dos tablas por fecha, Resultado:

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

que sé cómo agrupar una sola tabla,

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

¿Cómo puedo grupo de ambos? thx!

Respuesta

9

Dado que ambas tablas parecen tener una estructura similar, recomendaría proyectar ambas en una forma equivalente y luego agrupar en la concatenación de esos dos conjuntos.

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

Debido a la naturaleza perezosa de Linq2Sql esto en realidad podría reducirse a una sola consulta. En interés del rendimiento, me aseguraría de que esta no sea una pregunta del infierno.

+0

¿me puede dar un ejemplo, por favor? – dano

+0

¡gracias! , esperaba poder usar comandos regulares de linq/sql, no estaba pensando en combinar las dos tablas. ¿harías lo mismo si esto fuera simple TSQL? – dano

+0

En TSQL usaría una combinación externa completa, pero esto no es fácil en L2S, espero que la solución que proporcioné sea más simple que escribir una combinación externa completa. Simplemente busque SO si desea más información sobre cómo usar un FOJ en Linq. –

1

Se puede utilizar el método de la Unión:

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

Esto es muy similar al SQL que iba a escribir (una unión de dos tablas, y luego una consulta externa para combinar los resultados en una fila)

+0

thx eso es realmente similar a la respuesta "Johannes Rudolph". – dano

+0

Sí, pero es más probable que dé como resultado una sola instrucción SQL. Es mejor ponerlos a ambos y mirar el depurador :) –

+1

im getting "Todas las consultas combinadas usando un operador UNION, INTERSECT o EXCEPT deben tener un número igual de expresiones en sus listas de destino", piense que si las tablas tienen fechas diferentes, la consulta lo hará fallar – dano