c# -如何用聚合SQL作为LINQ查询最优雅地表示左连接

Translate

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
This question and all comments follow the "Attribution Required."

所有的回答

Translate

一种解决方案,尽管可以将空值的处理推迟到代码中,但可以是:

昨天的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,但是会提供相同的逻辑结果。将“复杂” SQL查询转换为LINQ并非总是那么简单。

来源
Hyman Lee
Translate
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()
    };

只需上述代码,就可以正常工作!

来源
Translate

对于您来说,这不是一个完整的答案,但是在左侧的连接块上,您可以像这样使用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。

来源
Translate

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