Сведения о вопросе

Fhohir

16:03, 1st July, 2020

Теги

c#   linq   left-join    

Как мне наиболее элегантно выразить left join с помощью запроса aggregate SQL as LINQ

Просмотров: 469   Ответов: 4

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



  Сведения об ответе

Chhiki

18:03, 1st July, 2020

Решением, хотя и таким, которое откладывает обработку значения null в коде, может быть:

DateTime вчера = 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()
    };

Это не дает точно такой же SQL, но дает тот же самый логический результат. Перевод "complex" SQL запросов в LINQ не всегда прост.


  Сведения об ответе

прога

18:03, 1st July, 2020

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

Просто вы видите приведенный выше код, и это должно работать нормально!


  Сведения об ответе

repe

18:03, 1st July, 2020

Это не полный ответ для вас, но на части left join вы можете использовать оператор DefaultIfEmpty примерно так:

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'

У меня еще не было необходимости выполнять какие-либо команды groupby, поэтому я оставил это, чтобы не посылать вас по неправильному пути. Есть еще две быстрые вещи, которые стоит отметить. Я не смог на самом деле присоединиться к двум параметрам, хотя, как и выше, есть способы обойти это. А еще, что ?? оператор работает очень хорошо вместо isnull в SQL.


  Сведения об ответе

prince

18:03, 1st July, 2020

Вы захотите использовать конструкцию join into для создания группового запроса.

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться