Wie kommt man zur MAX-Reihe?

20

In SQL Server war es immer schwierig, die maximalen Zeilen für ein Dataset abzurufen. Ich suche nach einer Liste der Methoden zum Abrufen der maximalen Zeilen mit einigen Hinweisen zu Leistung und Wartbarkeit.

Beispieltabelle:

DECLARE @Test TABLE (ID INT IDENTITY(1,1), name VARCHAR(50), 
                     dateOfBirth DATETIME, TaxNumber varchar(10))

INSERT INTO @Test (name, dateOfBirth, TaxNumber)
SELECT 'Fred', convert(datetime, '25/01/1976', 103), '123' UNION ALL
SELECT 'Bob', convert(datetime, '03/03/1976', 103), '234'  UNION ALL
SELECT 'Jane', convert(datetime, '13/06/1996', 103), '345' UNION ALL
SELECT 'Fred', convert(datetime, '14/02/1982', 103), '456' UNION ALL
SELECT 'Bob', convert(datetime, '25/10/1983', 103), '567' UNION ALL
SELECT 'Jane', convert(datetime, '12/04/1995', 103), '678' UNION ALL
SELECT 'Fred', convert(datetime, '03/03/1976', 103), '789'

select * from @Test

Gibt:

ID          name      dateOfBirth             TaxNumber
----------- --------- ----------------------- ----------
1           Fred      1976-01-25 00:00:00.000 123
2           Bob       1976-03-03 00:00:00.000 234
3           Jane      1996-06-13 00:00:00.000 345
4           Fred      1982-02-14 00:00:00.000 456
5           Bob       1983-10-25 00:00:00.000 567
6           Jane      1995-04-12 00:00:00.000 678
7           Fred      1976-03-03 00:00:00.000 789

Welche Methoden kann ich verwenden, wenn ich die älteste Person (nach Namen gruppiert) vollständig abrufen möchte?

Gewünschte Ausgabe:

ID          name      dateOfBirth             TaxNumber
----------- --------- ----------------------- ----------
1           Fred      1976-01-25 00:00:00.000 123
2           Bob       1976-03-03 00:00:00.000 234
6           Jane      1995-04-12 00:00:00.000 678
Andrew Bickerton
quelle

Antworten:

20

Zwei übliche Methoden: Aggregat- und Rangfolgefunktion.

Das Aggregat funktioniert unter SQL Server 2000. In beiden Fällen kann ein CTE oder eine abgeleitete Tabelle verwendet werden

Für die Leistung habe ich festgestellt, dass das Aggregat besser funktioniert. Es sieht jedoch so aus, als würden SQL Server 2008-Ranglistenfunktionen weitaus besser ausgeführt als unter SQL Server 2005. Ich verwende SQL Server 2008 noch nicht täglich (großes Dinsoaur-Unternehmen), kann also keine Kommentare abgeben.

Es gibt 2 relevante SO-Fragen, aber ich kann sie derzeit nicht finden. Eine ist eine Frage zu High Logic IO mit Ranking-Funktionen, eine andere ist das Testen des Rankings in Kommentaren über SQL 2k5 vs. 2k8. Es tut uns leid.

--aggregate + CTE
;WITH cOldest AS
(
    SELECT name, MIN(dateOfBirth) AS MinDOB FROM @Test GROUP BY name
)
SELECT
    T.*
FROM
    @Test T
    JOIN
    cOldest C ON T.name = C.name AND T.dateOfBirth = C.MinDOB
ORDER BY
    T.ID

--aggregate + derived table
SELECT
    T.*
FROM
    @Test T
    JOIN
    (
    SELECT name, MIN(dateOfBirth) AS MinDOB FROM @Test GROUP BY name
    ) C ON T.name = C.name AND T.dateOfBirth = C.MinDOB
ORDER BY
    T.ID

--ranking + CTE
;WITH cOldest AS
(
    SELECT *, ROW_NUMBER() OVER (PARTITION BY name ORDER BY dateOfBirth) AS rnDOB FROM @Test
)
SELECT
    C.*
FROM
    cOldest C
WHERE
    C.rnDOB = 1
ORDER BY
    C.ID

--ranking + derived table
SELECT
    C.*
FROM
    (SELECT *, ROW_NUMBER() OVER (PARTITION BY name ORDER BY dateOfBirth) AS rnDOB FROM @Test) C
WHERE
    C.rnDOB = 1
ORDER BY
    C.ID
gbn
quelle