Como expresso a junção esquerda de maneira mais elegante com SQL agregado como consulta LINQ

StackOverflow https://stackoverflow.com/questions/832

  •  08-06-2019
  •  | 
  •  

Pergunta

SQL:

SELECT
   u.id,
   u.name,
   isnull(MAX(h.dateCol), '1900-01-01') dateColWithDefault
FROM universe u
LEFT JOIN history h 
   ON u.id=h.id 
   AND h.dateCol<GETDATE()-1
GROUP BY u.Id, u.name
Foi útil?

Solução

Uma solução, embora que adie o tratamento do valor nulo para o código, poderia ser:

DateTime ontem = DateTime.Now.Date.AddDays(-1);

var collection=
    from u in db.Universe
    select new
    {
        u.id,
        u.name,
        MaxDate =(DateTime?)
       (
           from h in db.History
           where u.Id == h.Id
           && h.dateCol < yesterday
           select h.dateCol 
       ).Max()
    };

Isso não produz exatamente o mesmo SQL, mas fornece o mesmo resultado lógico.A tradução de consultas SQL "complexas" para LINQ nem sempre é simples.

Outras dicas

var collection=
    from u in db.Universe
    select new
    {
        u.id,
        u.name,
        MaxDate =(DateTime?)
       (
           from h in db.History
           where u.Id == h.Id
           && h.dateCol < yesterday
           select h.dateCol 
       ).Max()
    };

Basta usar o código acima e isso deve funcionar bem!

Esta não é uma resposta completa para você, mas na junção esquerda você pode usar o operador DefaultIfEmpty assim:

var collection = 
from u in db.Universe
join history in db.History on u.id = history.id into temp
from h in temp.DefaultIfEmpty()
where h.dateCol < DateTime.Now.Date.AddDays(-1)
select u.id, u.name, h.dateCol ?? '1900-01-01'

Ainda não tive a necessidade de executar nenhum comando groupby, então deixei isso de lado para não enviar você para o caminho errado.Duas outras coisas rápidas a serem observadas.Na verdade, não consegui unir dois parâmetros, embora, como acima, existam maneiras de contornar isso.Também o ??O operador funciona muito bem no lugar do isnull no SQL.

Você vai querer usar o join into construa para criar uma consulta de grupo.

TestContext db = new TestContext(CreateSparqlTripleStore());
var q = from a in db.Album
        join t in db.Track on a.Name equals t.AlbumName into tracks
        select new Album{Name = a.Name, Tracks = tracks};
foreach(var album in q){
    Console.WriteLine(album.Name);
    foreach (Track track in album.Tracks)
    {
        Console.WriteLine(track.Title);
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top