我如何最优雅地表达与SQL聚合的左连接作为LINQ查询

cnon 发布于 2018-02-05 c# 最后更新 2018-02-05 01:04 414 浏览

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
已邀请:

cnon

赞同来自:

一个解决方案,虽然延迟处理空值的代码,可能是:

DateTime yesterday = 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,但会提供相同的逻辑结果。将“复杂的”SQL查询翻译成LINQ并不总是直截了当的。

zearum

赞同来自:

这不是一个完整的答案,但在左边的连接部分,您可以使用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命令,所以我把它留下来,不要把你送到错误的路上。另外两个要注意的事情。尽管如上所述,我还是无法真正加入两个参数。另外,??在SQL中,操作符能够很好地代替isnull。

tquod

赞同来自:

您将要使用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);
    }
}

funde

赞同来自:

CODE_0的PLACEHOLDER 只要使用上面的代码,这应该工作得很好!