Doppelte Daten anzeigen die nicht exact doppelt sind!
Hallo zusammen,
ich habe eine Tabelle GRUNDWASSER die seit über 20 Jahren täglich mit Messdaten von ettlichen Loggern gefüttert wird.
Es ist aufgefallen das manche Logger die Messdaten doppelt geschickt haben ( warscheinlich auf schlechte Verbindung der SIM Karten im Logger zurückzuführen). Jetzt möchte ich mir sämtliche dieser doppelten Einträge anzeigen lassen.
Das Problem bei der ganzen Sache ist , dass das Datum mit Uhrzeit in einer Spalte steht und die doppelten daten somit nicht identisch !
Die Messdaten sind die gleichen allerdings mit anderem Zeitstempel.
Tabelle : Grundwasser
Spalte a: Datum (date) : 10.06.2016 00:00:40
Spalte b: Geräte ID (number) : 4558
Es sollen jetzt alle IDs gelistet werden die doppelt geliefert haben.
Ich steh gerade voll auf dem Schlauch.
Ich hoffe Ihr könnt mir helfen....
Grüße
ich habe eine Tabelle GRUNDWASSER die seit über 20 Jahren täglich mit Messdaten von ettlichen Loggern gefüttert wird.
Es ist aufgefallen das manche Logger die Messdaten doppelt geschickt haben ( warscheinlich auf schlechte Verbindung der SIM Karten im Logger zurückzuführen). Jetzt möchte ich mir sämtliche dieser doppelten Einträge anzeigen lassen.
Das Problem bei der ganzen Sache ist , dass das Datum mit Uhrzeit in einer Spalte steht und die doppelten daten somit nicht identisch !
Die Messdaten sind die gleichen allerdings mit anderem Zeitstempel.
Tabelle : Grundwasser
Spalte a: Datum (date) : 10.06.2016 00:00:40
Spalte b: Geräte ID (number) : 4558
Es sollen jetzt alle IDs gelistet werden die doppelt geliefert haben.
Ich steh gerade voll auf dem Schlauch.
Ich hoffe Ihr könnt mir helfen....
Grüße
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 306769
Url: https://administrator.de/contentid/306769
Ausgedruckt am: 12.11.2024 um 22:11 Uhr
26 Kommentare
Neuester Kommentar
Moin Chillministrator,
wenn es wirklich eine Oracle-DB ist, dann wird dir
Mit
Beispiel:
Bei deiner Tabelle musst du dich dann entscheiden, ob in dem Falle "doppelter" Logger-Datenlieferungen
a) die erste Lieferung eines Tages die einzig wahre & gültige ist und alle anderen to be ignored
b) die letzte Datenlieferung eines Tages die einzig wahre & gültige ist, weil... die frischeste Lieferung eines Tages gewinnen soll.
So oder so kannst du dann alle GRUN_MOBJ_IDs+GRUN_DATUM-Sätze aus der Tabelle GRUNDWASSER holen für die gilt
Ob nun ...min(GRUN_DATUM) oder ...max(GRUN_DATUM) das Gewünschte ist, musst du festlegen (s.o.)
[Edit]
Alternativ zu der
Falls das Dtaenvolumen deiner Messwerte wirklich für alle Messdaten tagesweise rückwirkend bis 1994 durchgepflügt werden soll, könnte die obige Skizze evtl. ein wenig inperformant sein.
[/Edit]
Grüße
Biber
wenn es wirklich eine Oracle-DB ist, dann wird dir
TRUNC()
weiterhelfen.Mit
trunc(datumswert)
kannst du den Zeit-Anteil (Stunden, Minuten, Sekunden...) aus einem Datumswert "streichen".Beispiel:
Select sysdate, trunc(sysdate) from dual;
SYSDATE | TRUNC(SYSDATE)
------------------------+------------------------
10.06.2016 11:39:33,000 | 10.06.2016 00:00:00,000
Bei deiner Tabelle musst du dich dann entscheiden, ob in dem Falle "doppelter" Logger-Datenlieferungen
a) die erste Lieferung eines Tages die einzig wahre & gültige ist und alle anderen to be ignored
b) die letzte Datenlieferung eines Tages die einzig wahre & gültige ist, weil... die frischeste Lieferung eines Tages gewinnen soll.
So oder so kannst du dann alle GRUN_MOBJ_IDs+GRUN_DATUM-Sätze aus der Tabelle GRUNDWASSER holen für die gilt
SELECT * from GRUNDWASSER
WHERE ( GRUN_MOBJ_ID, GRUN_DATUM) in (
SELECT GRUN_MOBJ_ID, min(GRUN_DATUM) from GRUNDWASSER
GROUP BY GRUN_MOBJ_ID, GRUN_DATUM
)
Ob nun ...min(GRUN_DATUM) oder ...max(GRUN_DATUM) das Gewünschte ist, musst du festlegen (s.o.)
[Edit]
Alternativ zu der
..WHERE ...IN (Select ...from)
-Bedingung ginge es auch über analytische Funktionen ( Aggregatfunktion und Partition by Trunc(GRUN_DATUM)
.Falls das Dtaenvolumen deiner Messwerte wirklich für alle Messdaten tagesweise rückwirkend bis 1994 durchgepflügt werden soll, könnte die obige Skizze evtl. ein wenig inperformant sein.
[/Edit]
Grüße
Biber
Bei SQL könnte man es auch so angehen:
Du würdest zu jedem Datensatz alle Datensätze dazu joinen die
a) die selbe Geräte ID haben
b) den selben Messwert (ich verstehe das so das der zwingend gleich ist)
c) die jeweils 5 Minuten nach dem jetzigen Datensatz eingetroffen sind. Die Zeitspanne läßt sich natürlich ändern. dateadd() ist jetzt eine MSSQL Funktion, Oracle hat bestimmt auch eine um Minuten zu addieren.
Du würdest dann beide Datensätze nebeneinander sehen und könntest so Dubletten erstmal finden. Ich denke mal das eine Nachkontrolle oder etwas derartiges auch erfolgen soll?
Mit trunc() hast du den Nachteil das du immer einen Zeitsprung nicht erkennen wirst, z.B. von 23:59:59 auf 00:00:00.
SELECT *
FROM grundwasser g1
INNER JOIN grundwasser g2
ON g1.number = g2.number
AND g1.messwert = g2.messwert
AND g2.[date] BETWEEN g1.[date] AND dateadd(mi,5,g1.[date])
a) die selbe Geräte ID haben
b) den selben Messwert (ich verstehe das so das der zwingend gleich ist)
c) die jeweils 5 Minuten nach dem jetzigen Datensatz eingetroffen sind. Die Zeitspanne läßt sich natürlich ändern. dateadd() ist jetzt eine MSSQL Funktion, Oracle hat bestimmt auch eine um Minuten zu addieren.
Du würdest dann beide Datensätze nebeneinander sehen und könntest so Dubletten erstmal finden. Ich denke mal das eine Nachkontrolle oder etwas derartiges auch erfolgen soll?
Mit trunc() hast du den Nachteil das du immer einen Zeitsprung nicht erkennen wirst, z.B. von 23:59:59 auf 00:00:00.
Es hätte Dir viel schneller geholfen werden können, wenn Du gleich gesagt hättest, in welchem Format das Zeug vorliegt und in welcher Sprache Du die Statements brauchst. Wenn man das einem erst langsam aus der Nase ziehen muß, dauert es halt länger.
Schönen Freitag noch.
lks
Na ja, ukulele-7,
dann können wir ja deine Strategie etwas variieren...
Hier würden jetzt (in der Theorie, da ungetestet) nur die Sätze im Resultset auftauchen, für die kein Datensatz mit gleichen IDs+Messwerten innerhalb der nächsten 2 Stunden existiert. Wobei auch 2 Stunden eher ein bisschen knapp kalkuliert ist...
Zur Anzeige nur der "doppelten" einfach das "not exists" in ein "exists" ändern.
Allerdings bleibt dann bei dieser Strategie das Problem, dass bei zwei Datenlieferungen an einem Tag mit UNgleichen Messwerten (also zB. eine marode Messung von 8.00h und einer korrigierten+korrekten von 9.00h) beide Datensätze relevant sind.
Bei meiner Strategie gäbe es immer max. 1 pro Tag.
Grüße
Biber
dann können wir ja deine Strategie etwas variieren...
SELECT *
FROM grundwasser g1
Where not exists (
SELECT 1 FROM grundwasser g2
WHERE g1.number = g2.number
AND g1.messwert = g2.messwert
AND g2.GRUN_DATUM BETWEEN g1.date AND g1.GRUN_DATUM + interval '2' hour)
Hier würden jetzt (in der Theorie, da ungetestet) nur die Sätze im Resultset auftauchen, für die kein Datensatz mit gleichen IDs+Messwerten innerhalb der nächsten 2 Stunden existiert. Wobei auch 2 Stunden eher ein bisschen knapp kalkuliert ist...
Zur Anzeige nur der "doppelten" einfach das "not exists" in ein "exists" ändern.
Allerdings bleibt dann bei dieser Strategie das Problem, dass bei zwei Datenlieferungen an einem Tag mit UNgleichen Messwerten (also zB. eine marode Messung von 8.00h und einer korrigierten+korrekten von 9.00h) beide Datensätze relevant sind.
Bei meiner Strategie gäbe es immer max. 1 pro Tag.
Grüße
Biber
Moin Chillministrator,
na ja, zwei wesentliche Fragen sollten wir vorher klären:
a) auf welchen Feldern liegen denn Indizes, die irgendwie nutzbar wären? Evtl. würde es die Recherche durchaus beschleunigen, wenn ein nicht-unique-Index auf
b) was genau ist denn dein Plan? Willst du "nur" in der Auswertung die logisch doppelten Sätze ausfiltern oder willst du alle anzeigen, die vermutlich Duplikate sind und die dann sukzessive nach Sichtkontrolle aus der Tabelle löschen?
Wenn so ein Index angelegt wäre, dann könntest du die Duplikate+das dazugehörige Original herausbekommen mit
Wie gesagt, wenn wenigstens irgendein Index unterstützend zur Verfügung steht, können wir ernsthaft reden.
So kennen wir ja nicht mal das Mengengerüst, also wissen nicht, ob wir durch 3MByte oder 55TByte Daten durchpflügen.
Grüße
Biber
na ja, zwei wesentliche Fragen sollten wir vorher klären:
a) auf welchen Feldern liegen denn Indizes, die irgendwie nutzbar wären? Evtl. würde es die Recherche durchaus beschleunigen, wenn ein nicht-unique-Index auf
trunc(GRUN_DATUM), GRUN_MOBJ_ID
angelegt werden würde. Denn die Laufzeit ist momentan unterirdisch, weil zwei full table scans aud die gesamte Monstertabelle gemacht werdenb) was genau ist denn dein Plan? Willst du "nur" in der Auswertung die logisch doppelten Sätze ausfiltern oder willst du alle anzeigen, die vermutlich Duplikate sind und die dann sukzessive nach Sichtkontrolle aus der Tabelle löschen?
Wenn so ein Index angelegt wäre, dann könntest du die Duplikate+das dazugehörige Original herausbekommen mit
select * from GRUNDWASSER g1
where (Trunc(GRUN_DATUM), GRUN_MOBJ_ID, GRUN_HOCHREL) IN
( Select Trunc(GRUN_DATUM), GRUN_MOBJ_ID, GRUN_HOCHREL
FROM GRUNDWASSER g2
-- optional zum Test: where grun_mobj_id <= 9998
GROUP BY Trunc(GRUN_DATUM), GRUN_MOBJ_ID, GRUN_HOCHREL
Having count(*) > 1
)
Wie gesagt, wenn wenigstens irgendein Index unterstützend zur Verfügung steht, können wir ernsthaft reden.
So kennen wir ja nicht mal das Mengengerüst, also wissen nicht, ob wir durch 3MByte oder 55TByte Daten durchpflügen.
Grüße
Biber
Moin,
Wenn das in der DB selbst solange dauert, was spricht dagegen, einfach alle Datensätze in eine csv zu exportieren, mit einem C-Program (oder shellscript) druchzunudeln und sich eine Liste mit den zu löschenden Datensätzen geben zu lassen und diese dann in der DB zu löschen?
Wäre zumindest mein pragmatischer Ansatz, wenn es innerhalb der DB zu langsam geht.
lks
Wenn das in der DB selbst solange dauert, was spricht dagegen, einfach alle Datensätze in eine csv zu exportieren, mit einem C-Program (oder shellscript) druchzunudeln und sich eine Liste mit den zu löschenden Datensätzen geben zu lassen und diese dann in der DB zu löschen?
Wäre zumindest mein pragmatischer Ansatz, wenn es innerhalb der DB zu langsam geht.
lks
Moin Chillministrator,
bin ja durchaus bereit dir zu helfen, auch mit analytic functions, ich möchte nur nicht total im Nebel stochern.
Ohne nutzbare Indizes kommen wir nicht weit, egal mit welcher Strategie.
Was ich bisher von deiner Tabelle weiss, ist;
Fragen dazu:
Das Performanzproblem bei einem INNER JOIN liegt daran, dass vermutlich beide Tabellen (G1 und G2) sequentiell gelesen werden, also jeder gottverdammte Satz angefasst wird (Full table scan). [Dazu müste aber auch der Ausführungsplan/das EXPLAIN etwas aussagen.] Davon müssen wir jedenfalls weg - wir sollten den potentiell relevanten SubSet der Tabelle, der überhaupt Duplikate enthalten kann, eingrenzen/wirksam filtern.
Dazu noch die Frage: diese wie auch immer verursachten Doppeldatenlieferungen traen schon immer auf seit 20 Jahren oder nur im Jahr 2009 oder nur vom 15.04.2015 bis 29.11.2015 oder wie ist der Sachverhalt?
Wenn das alles diesen Thread sprengen würde, dann lass uns diese Details über PN austauschen.
Grüße
Biber
bin ja durchaus bereit dir zu helfen, auch mit analytic functions, ich möchte nur nicht total im Nebel stochern.
Ohne nutzbare Indizes kommen wir nicht weit, egal mit welcher Strategie.
Was ich bisher von deiner Tabelle weiss, ist;
ich habe eine Tabelle GRUNDWASSER die seit über 20 Jahren täglich mit Messdaten von ettlichen Loggern gefüttert wird.
Und die Struktur der Tabelle, die du in einem deiner ersten Kommentare gepostet hast.Fragen dazu:
- wenn die Logger Daten liefern, tun sie das "täglich", sagst du. Bedeutet: planmäßig 1x täglich oder täglich im Stundentakt oder welcher Frequenz? Wie viele Datenlieferungen sind denn pro Tag da?
- Wenn ich diese Tabelle angelegt hätte, dann als partionierte Tabelle (also zB. je eine Partition für einen Monat oder ein Quartal, jedenfalls für einen Zeitraum). Denn in der Regel müssten die meisten Fragestellungen im täglichen Auswerten sich auf einen Teil oder alle der GRUN_MOBJ_IDs im gleichen Zeitraum (April 2013 oder Jahr 2016...) beziehen. Deshalb wäre es natürlich geschickter, wenn alle relevanten Daten sich in einer oder in wenigen Partitionen befinden. Hat das euer DBA auch so gesehen/ist dem so?
Das Performanzproblem bei einem INNER JOIN liegt daran, dass vermutlich beide Tabellen (G1 und G2) sequentiell gelesen werden, also jeder gottverdammte Satz angefasst wird (Full table scan). [Dazu müste aber auch der Ausführungsplan/das EXPLAIN etwas aussagen.] Davon müssen wir jedenfalls weg - wir sollten den potentiell relevanten SubSet der Tabelle, der überhaupt Duplikate enthalten kann, eingrenzen/wirksam filtern.
Dazu noch die Frage: diese wie auch immer verursachten Doppeldatenlieferungen traen schon immer auf seit 20 Jahren oder nur im Jahr 2009 oder nur vom 15.04.2015 bis 29.11.2015 oder wie ist der Sachverhalt?
Wenn das alles diesen Thread sprengen würde, dann lass uns diese Details über PN austauschen.
Grüße
Biber