Linke Verbindung mit einer Reihe

Ich habe eine SQL server-Abfrage, die so aussieht:

SELECT ListingId, hh.DateAltered FROM Listings (NOLOCK) LEFT JOIN ( SELECT h.ParentId, h.DateAltered FROM History AS h WHERE h.ParentType = 'Listing' ) hh ON hh.ParentId = Listings.ListingId WHERE ListingId = 56082 

Also im Grunde habe ich zwei Tische, Listings und History . Die Listings Tabelle hat nur 1 Zeile. Die History Tabelle hat 5 Zeilen, die mit dem Listings Tabellendatensatz verknüpft sind (wie Sie es aus der LEFT JOIN erzählen können).

Wenn ich die obige Abfrage ausführe, dann gibt es 5 Zeilen zurück. Dies ist, weil die History Tabelle 5 Zeilen hat, die mit der 1 Zeile in der Listings Tabelle verknüpft sind.

 ListingId DateAltered 56082 2013-11-06 09:27:29.647 56082 2013-11-08 14:30:42.543 56082 2013-11-08 15:11:30.390 56082 2013-11-14 09:54:21.060 56082 2014-01-09 16:23:52.440 

Aber ich brauche nur 1 Zeile aus der History Tabelle, also kann ich sehen, was das letzte DateAltered ist.

Also dachte ich, es wäre so einfach wie das Hinzufügen eines TOP(1) zur LEFT JOIN Abfrage:

 SELECT ListingId, hh.DateAltered FROM Listings (NOLOCK) LEFT JOIN ( SELECT TOP(1) h.ParentId, h.DateAltered FROM History AS h WHERE h.ParentType = 'Listing' ) hh ON hh.ParentId = Listings.ListingId WHERE ListingId = 56082 

Es gibt 1 Zeile jetzt zurück (was ist was ich will), aber jetzt die DateAltered Spalte ist NULL :

 ListingId DateAltered 56082 NULL 

Warum passiert dies? Und wie kann ich dieses Problem lösen?

Es passiert, weil die top 1 Aufnahme, die Sie ausgewählt haben, nicht die gleiche ID wie Ihre Listings-Tabelle hat.

Sie wollen den aktuellsten datasatz aus der History-Tabelle, wo die ID übereinstimmt. Sie können dies mit row_number

 SELECT ListingId, hh.DateAltered FROM Listings (NOLOCK) LEFT JOIN ( select * from ( SELECT h.ParentId, h.DateAltered, ROW_NUMBER() over (partition by parentid order by datealtered desc) rn FROM History AS h WHERE h.ParentType = 'Listing' ) h where rn=1 ) hh ON hh.ParentId = Listings.ListingId WHERE ListingId = 56082 

Wenn du den letzten DateAltered Wert DateAltered , solltest du MAX und GROUP BY :

 SELECT ListingId, hh.DateAltered FROM Listings (NOLOCK) LEFT JOIN ( SELECT h.ParentId, MAX(h.DateAltered) AS DateAltered FROM History AS h WHERE h.ParentType = 'Listing' GROUP BY h.ParentId ) hh ON hh.ParentId = Listings.ListingId WHERE ListingId = 56082 

Sie sind mit nur einer Zeile aus der Geschichte, wo Sie nicht wissen, ob es eine passende parentid ist. Du kannst die Oberseite (1) in die Hauptabfrage stellen und sie sortieren.

 SELECT TOP(1) ListingId, hh.DateAltered FROM Listings (NOLOCK) LEFT JOIN ( SELECT h.ParentId, h.DateAltered FROM History AS h WHERE h.ParentType = 'Listing' ) hh ON hh.ParentId = Listings.ListingId WHERE ListingId = 56082 order by hh.DateAltered desc 

aber mein Vorschlag wäre, dies zu tun:

 SELECT l.ListingId , max(hh.DateAltered) as DateAltered FROM Listings (NOLOCK) l left join History AS hh ON hh.ParentId = l.ListingId and hh.ParentType = 'Listing' WHERE l.ListingId = 56082 group by l.ListingId 

die Ihnen die maximal gemeldeten pro listingid gibt.

Sie müssen eine Unterabfrage verwenden und einen Wert als Spalte zurückgeben

 SELECT ListingId, (SELECT max(h.DateAltered) FROM History AS h WHERE h.ParentId = Listings.ListingId and h.ParentType = 'Listing') as LatestDateAltered FROM Listings (NOLOCK) WHERE ListingId = 56082