mysql: Datensätze aus zwei Tabellen vergleichen


Sprint

Erfahrenes Mitglied
#1
Hallo zusammen,

ich habe hier eine Kundentabelle, bei der die Datensätze vor einem Update immer in eine Backup Tabelle kopiert werden um später feststellen zu können, ob sich in der Zwischenzeit an relevanten Feldern etwas geändert hat. Ich habe es jetzt hiermit probiert:
SQL:
SELECT kdnr
FROM   kunden k
       LEFT OUTER JOIN kundenhistory h
                    ON k.kdnr = h.kdnr
WHERE  k.vorname = h.vorname
       AND k.nachname = h.nachname
       AND k.firmenname = h.firmenname
       AND k.strasse = h.strasse
       AND k.hausnr = h.hausnr
       AND k.plz = h.plz
       AND k.ort = h.ort
       AND k.kdnr = 200001
Allerdings bekomme ich verständlicherweise den Fehler, daß kdnr in der History nicht eindeutig ist. Kann ich aber auch nicht sein, da ja mehrere Generationen von Backups auftreten können.
Eindeutig werden die Zeilen in der History durch eine laufende Nummer "backupid". Zudem wird der Zeitpunkt des Backups in einem Feld "backupdatum" festgehalten. Bei dem Vergleich soll immer mit dem neuesten Backup verglichen werden.

Kann mir da jemand bitte auf die Sprünge helfen?
 

Sprint

Erfahrenes Mitglied
#3
Ich habe es jetzt so lösen können:
SQL:
SELECT k.kdnr
FROM   kunden k,
        (select nachname, vorname, firmenname, strasse, hausnr, plz, ort, max(backupdatum)
        from kundenhistory) as h
WHERE  (k.vorname != h.vorname
       OR k.nachname != h.nachname
       OR k.firmenname != h.firmenname
       OR k.strasse != h.strasse
       OR k.hausnr != h.hausnr
       OR k.plz != h.plz
       OR k.ort != h.ort)
       AND k.kdnr = h.kdnr
Zumindest bekomme ich bei den ersten Tests die richtigen Ergebnisse. ;)

Vielen Dank für deine Hilfe!
 

Sprint

Erfahrenes Mitglied
#4
Leider doch nicht. :(

Ich habe die Abfrage noch etwas erweitern müssen, aber auch ohne die Erweiterung nimmt er nur den ersten Datensatz. Wenn erst im zweiten oder dritten eine Unterscheidung auftaucht, wird die nicht gefunden.
SQL:
SELECT     k.kdnr, kv.kvid
FROM    kunden k,
        kaufvertrag kv,
        (SELECT kdnr, nachname, vorname, firmenname, strasse, hausnr, plz, ort, max(backupdatum)
        FROM kundenhistory) as h
WHERE    (k.vorname != h.vorname
        OR k.nachname != h.nachname
        OR k.firmenname != h.firmenname
        OR k.strasse != h.strasse
        OR k.hausnr != h.hausnr
        OR k.plz != h.plz
        OR k.ort != h.ort)
        AND k.kdnr = h.kdnr
        AND kv.kplok = 0
        AND kv.storno = 0
        AND kv.kdnr = k.kdnr
Ich habe auch schon mit den OR bzw. != experimentiert, bringt aber auch nichts.

Ziel ist es, die Kunden- und Kaufvertragsnummern herauszufinden, bei denen sich in Adresse oder Namen etwas geändert hat, während der Handel noch nicht abgeschlossen ist.
 
Zuletzt bearbeitet:
#5
Ist logisch. Schau nochmals mein Tutorial an.
Nur den MAX-Wert zu nehmen macht noch gar nix. Die History-Daten mit dem Max-Wert zur Kundennummer filtern

Das sind die notwendigen Backupdaten, die du zum vergleichen brauchst
SQL:
select kh.*
from 
    kundenhistory kh,
    (
        select kdnr, max(backupdatum) as max_datum
        from kundenhistory
        group by kdnr
    ) khmax
where kh.kdnr = khmax.kdnr and kh.backupdatum = khmax.max_datum
 

Sprint

Erfahrenes Mitglied
#6
Ich muß ganz ehrlich gestehen, daß die SQL Scripte etwas zu hoch sind. So ganz kapiere ich nicht, was da passiert.
Inzwischen hatte ich aber noch mit der JOIN Variante experimentiert, da mir eingefallen war, daß es ja auch Kunden geben kann, die trotz Änderungen keine offenen Kaufverträge haben und die dürfen natürlich nicht mit ausgegeben werden.
Zusammen mit deinem letzten Hinweis bin ich jetzt zu dieser Abfrage gekommen, die mir jetzt zumindest das richtige Ergebnis auch über mehrere Datensätze ausgibt. Ich habe zu ein paar Kunden eine History angelegt, von denen zwei einen offenen KV haben und genau die beiden werden ausgegeben.
SQL:
SELECT    k.kdnr, kv.kvid
FROM    kaufvertrag kv,
        kunden k
INNER JOIN (select kdnr, nachname, vorname, firmenname, strasse, hausnr, plz, ort, max(backupdatum) as max_datum
        from kundenhistory
        GROUP BY kdnr) as h
        ON k.kdnr = h.kdnr
WHERE    (k.vorname != h.vorname
        OR k.nachname != h.nachname
        OR k.firmenname != h.firmenname
        OR k.strasse != h.strasse
        OR k.hausnr != h.hausnr
        OR k.plz != h.plz
        OR k.ort != h.ort)
        AND kv.kplok = 0
        AND kv.storno = 0
        AND kv.kdnr = k.kdnr
Wie gesagt, es soll der aktuelle Kundendatensatz mit der jüngsten History verglichen werden, aber nur die ausgegeben werden, die noch einen offenen KV haben.
 

Sprint

Erfahrenes Mitglied
#8
Nur den MAX-Wert zu nehmen macht noch gar nix. Die History-Daten mit dem Max-Wert zur Kundennummer filtern
Meintest du den? Ignoriert habe ich ihn nicht, nur vergessen.:oops:
Wie gesagt, ich war damit beschäftigt, das ganze auf JOIN umzustellen, um die Kaufverträge mit reinzubringen. Außerdem muß ja auch noch die aktuelle Kundentabelle mit rein, da ja noch der Vergleich mit den aktuellen Kundendaten fehlte. Wenn ich das aber jetzt noch mit reinnehme, bekomme ich die Fehlermeldung, daß k.kdnr in der ON Clause unbekannt ist.
SQL:
SELECT    k.kdnr, kv.kvid
FROM    kunden k,
        kundenhistory h,
        kaufvertrag kv
INNER JOIN (select kdnr, nachname, vorname, firmenname, strasse, hausnr, plz, ort, max(backupdatum) as max_datum
        from kundenhistory
        GROUP BY kdnr) as hmax
        ON k.kdnr = h.kdnr
WHERE    (k.vorname != hmax.vorname
        OR k.nachname != hmax.nachname
        OR k.firmenname != hmax.firmenname
        OR k.strasse != hmax.strasse
        OR k.hausnr != hmax.hausnr
        OR k.plz != hmax.plz
        OR k.ort != hmax.ort)
        AND kv.kplok = 0
        AND kv.storno = 0
        AND kv.kdnr = k.kdnr
        AND k.kdnr = hmax.kdnr
        AND h.backupdatum = hmax.max_datum
Ich hab da auch schon alle möglichen Reihenfolgen durchprobiert, bekomme aber immer den selben Fehler.
 
#9
Kannst du mir das erklären? Macht keinen Sinn:
SQL:
(select kdnr, nachname, vorname, firmenname, strasse, hausnr, plz, ort, max(backupdatum) as max_datum
        from kundenhistory
        GROUP BY kdnr)
MySQL verzeit zu viele Fehler. Bei allen anderen Datenbanken währe das ein Fehler.
Du gruppierst nach der kdnr. Gut.
Du berechnest das Maximum vom Datum. Gut.
Wenn gruppiert wird, was macht MySQL mit den anderen Feldern? Soll dort ein Zufallswert genommen werden? Oder danach gruppiert werden? MySQL gruppiert danach.
Ergo hast du im Endeffekt das:
SQL:
(select kdnr, nachname, vorname, firmenname, strasse, hausnr, plz, ort, max(backupdatum) as max_datum
        from kundenhistory
        GROUP BY kdnr, nachname, vorname, firmenname, strasse, hausnr, plz, ort)
Und somit gruppierst du allen Änderungen auf den Feldern. Das gibt pro Änderung eine Zeile.

Zum Vergleich:
SQL:
select kh.*
from 
    kundenhistory kh,
    (
        select kdnr, max(backupdatum) as max_datum
        from kundenhistory
        group by kdnr
    ) khmax
where kh.kdnr = khmax.kdnr and kh.backupdatum = khmax.max_datum
Da wird zuerst pro kdn das aktuellste Datum ermittelt und mit dem dann die entsprechenden Datensätze ermittelt. Das gibt wirklich pro kdnr den aktuellsten Backup
 

Neue Beiträge