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

Letzten Wert bei Mehrfachmessungen ermitteln

Dieses Thema im Forum "Microsoft SQL Server" wurde erstellt von kwakz, 3 April 2014.

  1. kwakz

    kwakz Aktiver Benutzer

    Hallo zusammen,

    ich habe eine Datenbank, in der Messwerte von Ventilen stehen. Jedes Ventil ist durch seine Seriennnummer gekennzeichnet. Jetzt kann es vorkommen, dass ein Ventil mehrfach gemessen wurde ... beispielsweise, wenn es im ersten Durchgang als NIO bewertet wurde. Die Messungen sind durch eine Mess-ID gekennzeichnet.

    Nun interessiert mich bei diesen Mehrfachmessungen immer nur der letzte Messwert, weil das Ventil mit diesem die Anlage verlassen hat. Die Frage wäre: Wie kann ich die Abfrage so gestalten, dass bei jedem Ventil immer der Messwert mit der größten Mess-ID verwendet wird?

    Mfg Daniel
     
  2. akretschmer

    akretschmer Datenbank-Guru

    Abfrage auf ID des Ventiles und max(xxx) mit xxx hier z.B. der Zeitpunkt der Messung oder der ID-der Messung, wenn diese immer steigt.

    Damit JOINst dann Deine Meßtabelle, um die konkreten Meßwerte zu erhalten. Du siehst jetzt den Weg?
     
  3. akretschmer

    akretschmer Datenbank-Guru

    Um es mal zu zeigen:

    Code:
    test=*# select * from ventile;
     sn | mess_id | wert
    ----+---------+------
      1 |  1 |
      1 |  2 |  27
      1 |  3 |  38
      2 |  4 |  12
      2 |  5 |
      2 |  6 |  31
      3 |  7 |  8
      4 |  8 |  12
    (8 rows)
    
    test=*# select ventile.sn, ventile.wert from ventile inner join (select sn, max(mess_id) from ventile group by sn) foo on ((ventile.sn, ventile.mess_id)=(foo.sn,foo.max)) order by sn;
     sn | wert
    ----+------
      1 |  38
      2 |  31
      3 |  8
      4 |  12
    (4 rows)
    
     
  4. ukulele

    ukulele Datenbank-Guru

    Es gibt eigentlich viele Wege. Aber alle Varianten haben gemeinsam das man nach der MessID vernünftig sortieren können muss. Wenn deine MessID nicht numerisch ist und aufsteigend vergeben wird solltest du auf ein Messdatum oder ähnliches zurück greifen.

    Hier mal noch ein alternativer Weg (Datum kann man ggf. dann mit MessID tauschen wenn numerisch und aufsteigend):
    Code:
    SELECT    t.seriennr,
            t.datum
    FROM    (
    
    SELECT    ROW_NUMBER() OVER (PARTITION BY seriennr ORDER BY datum DESC) AS zeilennr,
            seriennr,
            datum
    FROM    tabelle
    
    ) t
    WHERE    t.zeilennr = 1
     
  5. akretschmer

    akretschmer Datenbank-Guru

    Stimmt.

    Aus dem Bauch heraus halte ich Deine Variante aber schlechter als meine, weil da immer ein Full-Table-Scan nötig wäre, um row_number() zu berechnen. Bei meinem könnte ein Index helfen und somit ein deutlich schnellerer Indexscan greifen. Ungetestet jetzt alles.
     
  6. ukulele

    ukulele Datenbank-Guru

    Da kennst du dich dann besser aus, ich hab bei meinen kleinen DBs selten Performance fragen. Allerdings müsste ein Index auf seriennr,datum doch hier auch meine Abfrage beschleunigen oder sehe ich das falsch?
     
  7. akretschmer

    akretschmer Datenbank-Guru

    In Deinem inneren Select gehst Du komplett durch die Tabelle und berechnest je Row die row_number. Auf dem Resultat dann machst Du das äußere Select. Aber erst einmal machst Du halt ein Full-Table-Scan. Ob der Index der originalen Tabelle dann noch greift ist die nächste Frage ;-)
     
  8. akretschmer

    akretschmer Datenbank-Guru

    Antwort:

    Code:
    test=*# set enable_seqscan to off;
    SET
    test=*# create index idx2 on ventile (sn, wert);
    CREATE INDEX
    test=*# explain select ventile.sn, ventile.wert from ventile inner join (select sn, max(mess_id) from ventile group by sn) foo on ((ventile.sn, ventile.mess_id)=(foo.sn,foo.max)) order by sn;
      QUERY PLAN
    -------------------------------------------------------------------------------------------
     Merge Join  (cost=0.27..24.84 rows=1 width=8)
      Merge Cond: (ventile_1.sn = ventile.sn)
      Join Filter: (ventile.mess_id = (max(ventile_1.mess_id)))
      ->  GroupAggregate  (cost=0.13..12.37 rows=8 width=8)
      ->  Index Scan using idx2 on ventile ventile_1  (cost=0.13..12.25 rows=8 width=8)
      ->  Index Scan using idx2 on ventile  (cost=0.13..12.25 rows=8 width=12)
    (6 rows)
    
    
    
    -- deine version
    test=*# explain select t.* from (select row_number() over (partition by sn order by mess_id desc) as zn, * from ventile) t where t.zn=1;
      QUERY PLAN
    ----------------------------------------------------------------------------------------------
     Subquery Scan on t  (cost=10000000001.20..10000000001.46 rows=1 width=20)
      Filter: (t.zn = 1)
      ->  WindowAgg  (cost=10000000001.20..10000000001.36 rows=8 width=12)
      ->  Sort  (cost=10000000001.20..10000000001.22 rows=8 width=12)
      Sort Key: ventile.sn, ventile.mess_id
      ->  Seq Scan on ventile  (cost=10000000000.00..10000000001.08 rows=8 width=12)
    (6 rows)
    
     
    Walter und ukulele gefällt das.
  9. kwakz

    kwakz Aktiver Benutzer

    Hallo zusammen,

    vielen Dank für die Antworten. Ich hab jetzt im Prinzip die erste Lösung ein bisschen adaptiert. Ich erzeuge mir eine temporäre Tabelle und verknüpfe die dann mit einem Inner Join.

    Vielen Dank!

    Mfg Daniel
     
  10. ukulele

    ukulele Datenbank-Guru

    Ich hoffe damit meinst du eine View oder einen inneren Select und keine tatsächliche Kopie der Daten.
     
  11. kwakz

    kwakz Aktiver Benutzer

    Hm ... ich erzeuge eine temporäre Tabelle mit einer with-Anweisung ... sollte ich hier lieber einen View benutzen?
     
  12. akretschmer

    akretschmer Datenbank-Guru

    Sollte egal sein. Auch M$SQL kann wohl einen Ausführungsplan anzeigen, das sollte die beste Antwort sein.
     
  13. Hony%

    Hony% Datenbank-Guru

    Mit WITH erzeugst du im Grunde eine benannte Menge. Temporäre Tabellen werden hingegen physisch gespeichert. WITH ist schon ok und wäre mit einer temporären VIEW zu vergleichen.
     
  14. ukulele

    ukulele Datenbank-Guru

    Ich meinte das du keine zusätztliche Tabelle anlegen sollst in die du deine Daten kopierst um sie dann zu joinen. WITH ist voll i.O.
     
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