c# - Wie drücke ich Left Join mit aggregiertem SQL am elegantesten als LINQ-Abfrage aus?

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."

Alle Antworten

Translate

Eine Lösung, die die Behandlung des Nullwerts für den Code verzögert, könnte sein:

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

Dies erzeugt nicht genau das gleiche SQL, liefert aber das gleiche logische Ergebnis. Das Übersetzen "komplexer" SQL-Abfragen in LINQ ist nicht immer einfach.

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

Verwenden Sie einfach den obigen Code und dies sollte gut funktionieren!

Quelle
Translate

Dies ist keine vollständige Antwort für Sie, aber auf der linken Seite können Sie den Operator DefaultIfEmpty folgendermaßen verwenden:

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'

Ich hatte noch keine Notwendigkeit, Groupby-Befehle auszuführen, also habe ich das weggelassen, um Sie nicht auf den falschen Weg zu schicken. Zwei weitere schnelle Dinge zu beachten. Ich war nicht in der Lage, zwei Parameter tatsächlich zu verknüpfen, obwohl es wie oben Möglichkeiten gibt, dies zu umgehen. Auch der ?? Der Operator funktioniert sehr gut anstelle des isnull in SQL.

Quelle
Translate

Du wirst das benutzen wollenjoin intoKonstrukt zum Erstellen einer Gruppenabfrage.

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