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

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

  •  08-06-2019
  •  | 
  •  

Вопрос

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
Это было полезно?

Решение

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

Дата-время вчера = Дата-время.Сейчас.Дата.Добавленные дни(-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, но обеспечивает тот же логический результат.Перевод "сложных" SQL-запросов в LINQ не всегда прост.

Другие советы

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

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

Это не полный ответ для вас, но в левой части соединения вы можете использовать оператор 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, поэтому я опустил это, чтобы не направить вас по ложному пути.Следует отметить еще две быстрые вещи.Мне не удалось фактически объединить два параметра, хотя, как указано выше, есть способы обойти это.Кроме того, этот??operator действительно хорошо работает вместо isnull в SQL.

Вы наверняка захотите использовать 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);
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top