Einige Beispiele wie man pro Gruppe die Zeile mit dem neusten Datum ermitteln kann. Komplexere DBMS besitzen Analytische Funktionen, die so was abnehmen. Nicht aber MySQL und MS Access. Ergo muss hier auf diese Funktionen verzichtet werden.
Als Beispiel nehme ich eine einfache Währungskurs-Tabelle. Sie hat pro Währungs-kombination mehrere Einträge. nun möchte ich von jeder Kombination den aktuellsten Eintrag auslesen
[kurs] w1 | w2 | kurs | datum CHF | EUR | 0.779438988 | 2011-03-21 CHF | USD | 1.10045 | 2011-03-20 CHF | USD | 1.10314 | 2011-03-21 CHF | EUR | 0.872367653 | 2011-03-20 CHF | USD | 1.10112 | 2011-03-19
Dazu müssen wir erst einmal für jede Währungskombination das aktuellste Datum auslesen
SELECT w1, w2, MAX(datum) AS max_datum FROM kurs GROUP BY w1, w2;
Das ergibt dann die folgende Ausgabe
w1 | w2 | max_datum CHF | EUR | 2011-03-21 CHF | USD | 2011-03-21
nun interessiert uns aber der Umrechnungskurs zu diesen max_datum. Also müssen wir dieses Resultat wieder mit der Tabelle kurs verknüpfen. Dazu gibt es ganz unterschiedliche Varianten, die eigentlich genau das bewerkstelligen.
Die vorgestellten Lösungen ergeben immer dasselbe Resultat. Welches am performantesten ist, kann ich nicht pauschal beantworten. Bei kleineren Datenmengen ist es irrelevant und bei Grösseren kommt es stark auf Indexe, Datenzusammensetzung etc an.
Die Ausgabe wird immer so aussehen
w1 | w2 | kurs | datum CHF | EUR | 0.779438988 | 2011-03-21 CHF | USD | 1.10314 | 2011-03-21
MySQL, MS Access, Oracle
Das Subquery wird mittels WHERE-Beziehungen an die Daten geknüpft
SELECT k.* FROM kurs AS k, ( SELECT w1, w2, MAX(datum) AS max_datum FROM kurs GROUP BY w1, w2 ) AS le WHERE k.w1 = le.w1 AND k.w2 = le.w2 AND k.datum = le.max_datum;
MySQL, MS Access, Oracle
Dasselbe wie zuvor, einfach mit der INNER-JOIN-Schreibweise
SELECT k.* FROM kurs AS k INNER JOIN ( SELECT w1, w2, MAX(datum) AS max_datum FROM kurs GROUP BY w1, w2 ) AS le ON k.w1 = le.w1 AND k.w2 = le.w2 AND k.datum = le.max_datum;
MySQL, Oracle
Natürlich kann man das auch mit IN() im WHERE-Bereich erledigen
SELECT k.* FROM kurs AS k WHERE (k.w1, k.w2, k.datum) IN ( SELECT w1, w2, MAX(datum) AS max_datum FROM kurs GROUP BY w1, w2 );
MySQL, MS Access, Oracle
oder als Korrelierte Unterabfrage
SELECT k.* FROM kurs AS k WHERE k.datum IN ( SELECT MAX(datum) AS max_datum FROM kurs WHERE kurs.w1 = k.w1 AND kurs.w2 = k.w2 GROUP BY w1, w2 );
MS Access
In MS Access kann man auch mit DMAX() arbeiten. Mit DMAX() das aktuelleste Datum auslesen und im WHERE verknüpfen
SELECT k.* FROM kurs AS k WHERE k.datum = DMAX("datum", "kurs", "[w1]='" & k.w1 & "' AND [w2]='" & k.w2 & "'") ;
Nehmen wir an, wir wollen nun wissen, was der Kurs am 19ten war
Wir können einfach im inneren Query (Abfragedes aktuellen Datums) noch die Bedinung mit dem Datum hinzufügen. Also Datum der Tabelle ist kleiner oder gleich dem Selektionierten Datum.
Der Datumstring ist je nach DBMS. Oracle: TO_DATE('19.03.2011', 'DD.MM.YYYY'), Access: #03/19/2011#
SELECT w1, w2, MAX(datum) AS max_datum FROM kurs WHERE datum <= 2011-03-19 GROUP BY w1, w2 ;
Oder beim DMAX-Beispiel im Access:
WHERE k.datum = DMAX("datum", "kurs", "[w1]='" & k.w1 & "' AND [w2]='" & k.w2 & "' AND [datum] <= #03/19/2011#")