Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

höchste und zweithöchste ID ermitteln

Dieses Thema im Forum "MySQL und MariaDB" wurde erstellt von Knappe, 4 Februar 2015.

  1. Knappe

    Knappe Neuer Benutzer

    Hallo,

    ich möchte aus einer Tabelle die beiden höchsten IDs (Primärschlüssel) bestimmen, die zu einer größeren Anzahl an Datensätzen mit gemeinsamen Fremdschlüssel gehören.
    Und diese beiden Datensätze möchte ich für eine Differenz nutzen, also Wert des Satzes mit der höchsten ID minus Wert des Satzes mit der zweithöchsten ID.

    Beispiel:
    ID FK Wert
    1 1 12
    2 2 8
    3 3 5
    4 1 18
    5 4 3
    6 2 11
    7 1 23
    8 3 9


    Ich möchte also zum FK = 1 das Ergbnis aus 23 - 18 errechnen, denn
    23 ist der Wert zur ID 7 und die wiederum ist die höchste ID zum FK 1 und
    18 ist der Wert zur zweithöchsten ID (nämlich 4) zum FK 1.

    Kann mir jemand einen (simplen) Trick verraten, wie ich das bewerkstelligen kann?

    Danke vorab,
    Ralf
     
  2. ukulele

    ukulele Datenbank-Guru

    Also in MSSQL würde es so gehen:
    Code:
    SELECT    t1.id,
            t1.fk,
            t1.wert - isnull(t2.wert,0) AS wert
    FROM    (
    
    SELECT    ROW_NUMBER() OVER (PARTITION BY fk ORDER BY id DESC) AS zeile,
            id,fk,wert
    FROM    tabelle
    
    ) t1
    LEFT JOIN (
    
    SELECT    ROW_NUMBER() OVER (PARTITION BY fk ORDER BY id DESC) AS zeile,
            id,fk,wert
    FROM    tabelle
    
    ) t2
    ON        t1.fk = t2.fk
    AND        t2.zeile = 2
    WHERE    t1.zeile = 1
    Ich glaube MySQL kann auch ROW_NUMBER() aber eventuell etwas andere Syntax. isnull() müstest du auch noch ersetzen, dann könnte es so gehen.
     
  3. akretschmer

    akretschmer Datenbank-Guru

    Das ginge mit teuren DB-Systemen wie Oracle oder M$SQL oder der OpenSource-DB PostgreSQL mit Window-Funktionen (lag() in diesem Falle) sehr, sehr einfach. Mit MySQL nicht, das kann kaum etwas, was man 2015 von einer Datenbank erwarten kann.

    Warum nutzt man MySQL, wenn das, was man machen will, damit nicht geht? Klassische Fehlentscheidung.
     
  4. Knappe

    Knappe Neuer Benutzer

    Wow, "simpel" ist anders :eek:

    Ich werde mich gleich mal mit Deinem Hinweis beschäftigen und versuchen, da durchzusteigen. Auf jeden Fall schon einmal herzlichen Dank für die Antwort.
     
  5. Knappe

    Knappe Neuer Benutzer

    ...nun, das liegt daran, dass ich eine Weiterbildungsmaßnahme über die Arbeitsagentur mache und da halt MySQL vorgegeben wird :(
     
  6. Knappe

    Knappe Neuer Benutzer

    @ukulele:

    du hast bei t1 und t2 jeweils den Alias "zeile" verwandt. Klappst das so oder müssten die Aliase verscheiden heißen?
     
  7. Distrilec

    Distrilec Datenbank-Guru

    @Knappe Das klappt so... Sind ja verschiedene Tabellen-Aliase vergeben :) (t1 und t2)
     
  8. ukulele

    ukulele Datenbank-Guru

    Richtig, solange du immer explizite Schreibweisen wie t1.zeile oder t2.zeile verwendest wirst du keine Probleme bekommen.
     
  9. akretschmer

    akretschmer Datenbank-Guru

    Um das mal für Deine Daten zu zeigen:

    Du hast:
    Code:
    test=*# select * from knappe ;
     id | fk | wert
    ----+----+------
      1 |  1 |  12
      2 |  2 |  8
      3 |  3 |  5
      4 |  1 |  18
      5 |  4 |  3
      6 |  2 |  11
      7 |  1 |  23
      8 |  3 |  9
    (8 rows)
    
    Nun spielen wir mal a bissl mit Window-Funktionen, hier lead(), lag() und row_number()

    Code:
    test=*# select fk, wert, lag(wert) over(partition by fk order by wert desc), wert - lead(wert) over (partition by fk order by wert desc) asresultat, row_number() over (partition by fk order by wert desc) from knappe ;
     fk | wert | lag | resultat | row_number
    ----+------+-----+----------+------------
      1 |  23 |  |  5 |  1
      1 |  18 |  23 |  6 |  2
      1 |  12 |  18 |  |  3
      2 |  11 |  |  3 |  1
      2 |  8 |  11 |  |  2
      3 |  9 |  |  4 |  1
      3 |  5 |  9 |  |  2
      4 |  3 |  |  |  1
    (8 rows)
    
    Nun willst Du ja nur je FK das resultat:

    Code:
    test=*# select fk, resultat from (select fk, wert, lag(wert) over(partition by fk order by wert desc), wert - lead(wert) over (partition byfk order by wert desc) as resultat, row_number() over (partition by fk order by wert desc) from knappe ) foo where row_number = 1;
     fk | resultat
    ----+----------
      1 |  5
      2 |  3
      3 |  4
      4 |
    (4 rows)
    
    Einfach, oder?
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden