2012-10-17 4 views
16

Mögliche Duplizieren:
How to get the record of a table who contains the maximum value?SQL select max (Datum) und entsprechende Wert

ich ein Aggregat Abfrage wie die folgende haben:

SELECT TrainingID, Max(CompletedDate) as CompletedDate, Max(Notes) as Notes  --This will only return the longest notes entry 
FROM HR_EmployeeTrainings ET 
WHERE (ET.AvantiRecID IS NULL OR ET.AvantiRecID = @avantiRecID) 
GROUP BY AvantiRecID, TrainingID    

Welche ist funktioniert, und die meiste Zeit korrekte Daten zurückgibt, aber ich bemerkte ein Problem. Das Feld "Notes", das zurückgegeben wird, stimmt nicht unbedingt mit dem Datensatz überein, aus dem das Maximum (completedDate) stammt. Stattdessen wird es der mit der längsten Saite sein? Oder der mit dem höchsten ASCII-Wert? Was macht SQL Server im Falle einer Verbindung zwischen zwei Datensätzen? Ich bin mir nicht einmal sicher. Was ich erhalten möchte, ist das Notizenfeld aus dem Datensatz max (completedDate). Wie soll ich das machen?

+0

Ist CompletedDate keine DateTime? – Frobzig

+0

Es ist eine DateTime. Kein Problem mit diesem Feld, aber mit Notizen. – MAW74656

+0

die maximalen Noten oder jede Note für das 'max (completedDate)'? – Marc

Antwort

23

Sie eine Unterabfrage verwenden kann. Die Unterabfrage erhält die Max(CompletedDate). Sie nehmen dann diesen Wert und kommen wieder auf den Tisch die Notiz assoziieren mit diesem Zeitpunkt abzurufen:

select ET1.TrainingID, 
    ET1.CompletedDate, 
    ET1.Notes 
from HR_EmployeeTrainings ET1 
inner join 
(
    select Max(CompletedDate) CompletedDate, TrainingID 
    from HR_EmployeeTrainings 
    --where AvantiRecID IS NULL OR AvantiRecID = @avantiRecID 
    group by TrainingID 
) ET2 
    on ET1.TrainingID = ET2.TrainingID 
    and ET1.CompletedDate = ET2.CompletedDate 
where ET1.AvantiRecID IS NULL OR ET1.AvantiRecID = @avantiRecID 
3

Es gibt keine einfache Möglichkeit, dies zu tun, aber so etwas wie dies funktioniert:

SELECT ET.TrainingID, 
    ET.CompletedDate, 
    ET.Notes 
FROM 
HR_EmployeeTrainings ET 
inner join 
(
    select TrainingID, Max(CompletedDate) as CompletedDate 
    FROM HR_EmployeeTrainings 
    WHERE (ET.AvantiRecID IS NULL OR ET.AvantiRecID = @avantiRecID) 
    GROUP BY AvantiRecID, TrainingID 
) ET2 
    on ET.TrainingID = ET2.TrainingID 
    and ET.CompletedDate = ET2.CompletedDate 
+0

Sie Syntax ist falsch für Ihre Unterabfrage, Sie fehlen eine 'FROM'-Klausel. – Taryn

3

Jede MAX-Funktion einzeln ausgewertet wird. So wird MAX (CompletedDate) den Wert der letzten CompletedDate-Spalte und MAX (Notes) den maximalen Wert (d. H. Alphabetisch höchsten Wert) zurückgeben.

Sie müssen Ihre Abfrage anders strukturieren, um zu bekommen, was Sie wollen. Diese Frage war eigentlich schon gefragt und mehrmals beantwortet, so dass ich es nicht wiederholen:

How to find the record in a table that contains the maximum value?

Finding the record with maximum value in SQL

+1

Wenn die Frage schon oft beantwortet wurde, ist das richtige zu tun, um zu schließen, als "genaues Duplikat" – Tony

+0

Thx, das habe ich jetzt getan. – Marplesoft

5

Ah ja, das ist, wie es in SQL gedacht. Sie erhalten den Max jeder Spalte separat. Es scheint, als ob Sie Werte aus der Zeile mit dem maximalen Datum zurückgeben möchten. Wählen Sie daher die Zeile mit dem maximalen Datum aus. Ich ziehe es vor, dies mit einem Subselect zu tun, da die Abfragen kompakt lesbar bleiben.

SELECT TrainingID, CompletedDate, Notes 
FROM HR_EmployeeTrainings ET 
WHERE (ET.AvantiRecID IS NULL OR ET.AvantiRecID = @avantiRecID) 
AND CompletedDate in 
    (Select Max(CompletedDate) from HR_EmployeeTrainings B 
    where B.TrainingID = ET.TrainingID) 

Wenn Sie auch nach AntiRecID suchen möchten, sollten Sie das auch in den Subselect aufnehmen.