tutorials.de Buch-Aktion 05/2012
  • [MySQL] Aktuelle Einträge pro Gruppe auslesen

    Einige Beispiele, wie man in MySQL pro Gruppe die Zeile mit dem neuesten Datum ermitteln kann. In den meisten anderen Datenbanken funktioniert das vom Prinzip her gleich.

    Ausgangslage
    Als Beispiel nehme ich eine einfache Währungskurs-Tabelle. Sie hat pro Währungskombination mehrere Einträge. nun möchte ich von jeder Kombination den aktuellsten Eintrag auslesen
    Code :
    1
    2
    3
    4
    5
    6
    7
    
    [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

    Lösungsansatz
    Dazu müssen wir erst einmal für jede Währungskombination das aktuellste Datum auslesen
    Code sql:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    SELECT
        w1,
        w2,
        MAX(datum) AS max_datum
    FROM
        kurs
    GROUP BY
        w1,
        w2;
    Das ergibt dann die folgende Ausgabe
    Code :
    1
    2
    3
    
    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.

    Lösungen
    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
    Code :
    1
    2
    3
    
    w1  | w2  | kurs        | datum
    CHF | EUR | 0.779438988 | 2011-03-21
    CHF | USD | 1.10314     | 2011-03-21

    Einfaches Subquery mit WHERE-Verknüpfung
    Das Subquery wird mittels WHERE-Beziehungen an die Daten geknüpft
    Code sql:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    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;

    Einfaches Subquery mit INNER JOIN
    Dasselbe wie zuvor, einfach mit der INNER-JOIN-Schreibweise
    Code sql:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    SELECT
        k.*
    FROM
        kurs AS k
        INNER JOIN (
                    SELECT
                        w1,
                        w2,
                        MAX(datum) AS max_datum
                    FROM
                        kurs
                    GROUP BY
                        w1,
                        w2
                ) AS le --Last_entries
            ON
                k.w1 = le.w1
                AND k.w2 = le.w2
                AND k.datum = le.max_datum;

    Einfaches Subquery mit IN()
    Natürlich kann man das auch mit IN() im WHERE-Bereich erledigen
    Code sql:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    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
                                        );

    Korrelierte Unterabfrage
    oder als Korrelierte Unterabfrage
    Code sql:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    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
                        );


    Kommentare 1 Kommentar
    1. Avatar von Thomas Darimont
      Thomas Darimont -
      Hallo,

      ich habe den Artikel leider erst jetzt gesehen Klasse Beispiele!

      Ich glaube ich habe da aber noch eine Lösung-Variante für diese Problemstellung ... tief vergraben in den weiten unserer Datenbank

      http://www.tutorials.de/relationale-...arstellen.html

      Gruß Tom
    Kommentare Kommentar schreiben

    Klicke hier, um dich anzumelden

    Wie heißt die Hauptstadt der Bundesrepublik Deutschland?