集計 SQL を使用した左結合を LINQ クエリとして最もエレガントに表現するにはどうすればよいですか
質問
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
解決
Null 値の処理をコードに延期する解決策は次のとおりです。
昨日の日付時刻 = 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 に変換することは、必ずしも簡単ではありません。
他のヒント
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 コマンドを実行する必要がなかったので、間違ったパスに誘導されないように省略しました。他に注意すべき点が 2 つあります。上記のように、それを回避する方法はありますが、2つのパラメータで実際に結合できませんでした。また、??演算子は、SQL の isnull の代わりに非常にうまく機能します。
使いたくなるでしょう。 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);
}
}
所属していません StackOverflow