Autor Beitrag
TheUnknown
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 334



BeitragVerfasst: Fr 22.08.14 14:03 
Hallo,

die Gesamtsituation zu schildern, ist etwas komplex, darum beschreibe ich nur, was ich benötige, um es einfach und kurz zu halten.

Ich habe innerhalb derselben DB zwei Tables, die vollkommen gleich sind. Nennen wir die Tables TABLE A und TABLE B.

TABLE A und TABLE B haben dabei je ein Feld, dass "Datum" heißt. Und obwohl beide Datensätze identisch sind, sind bei TABLE A einige (nicht alle!) "Datum"-Angaben weit in der Vergangenheit, bei TABLE B sind sie alle von heute.

Was ich jetzt brauche, ist ein Query, das mir NUR diejenigen Datensätze aus TABLE A auflistet, bei denen sich die Feldinhalte von "Datum" zwischen TABLE A und TABLE B unterscheiden (wo es bei TABLE A also in der Vergangenheit ist). Ich fummel mir seit Stunden einen Wolf, aber es klappt nicht mal ansatzweise.

Kann mir da jemand helfen?
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Fr 22.08.14 14:11 
ausblenden SQL-Anweisung
1:
2:
3:
4:
5:
6:
7:
8:
select * 
  from TabelleA A
 where exists (select * 
                 from TabelleB B 
                where A.Feld1 = B.Feld1
                  and A.Feld2 = B.Feld2
                   -- u.s.w.
                  and A.Datum < B.Datum)
TheUnknown Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 334



BeitragVerfasst: Fr 22.08.14 14:25 
Vielen Dank, das war's! Endlich kann ich fortwärtskommen. :)
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Fr 22.08.14 22:27 
Das dürfte recht langsam sein, schließlich muss für jede Zeile von TableA jede Zeile von TableB neu verglichen werden.

Nur mal so in den Raum geworfen, kann es gerade nicht aus probieren:
Wenn die Tabellen einen Primärschlüssel haben, wo die Daten ebenfalls identisch sind, kann man die doch zusammen joinen und dann von jeder gejointen Datenzeile die Datum-Angaben vergleichen, oder?
Das müsste doch etwas schneller sein.
TheUnknown Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 334



BeitragVerfasst: Sa 23.08.14 08:11 
Jain. Es mag Möglichkeiten geben, die schneller oder "ordentlicher" sind, es ging mir um eine einmalige Angelegenheit. Ich brauchte das also nur einmal kurz und danach nicht mehr, darum war Performance und Eleganz nebensächlich.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 23.08.14 11:33 
Zitat:
Das dürfte recht langsam sein, schließlich muss für jede Zeile von TableA jede Zeile von TableB neu verglichen werden.


Ja, das machen join und exists aber identisch (unter der Annahme das der DB Hersteller keinen Mist programmiert hat). In einer einer gut implementierten Datenbank hat exists sogar eher das potential schneller zu sein als ein join. Ein exists kann ja beim ersten Treffer abbrechen während ein join alle Treffer verknüpfen muss unabhängig davon ob bei der Korrelation dann ein Table- oder Indexscan verwendet wird. Und da hast du natürlich recht wenn es ausreicht die beiden Tabellen so zu verknüpfen das ein Index zieht anstatt das ein Tablescan nötig ist sollte das eine positive Auswirkung haben.
Palladin007
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1282
Erhaltene Danke: 182

Windows 11 x64 Pro
C# (Visual Studio Preview)
BeitragVerfasst: Sa 23.08.14 20:35 
Es müssten aber alle Zeilen nur ein einziges mal verknüpft werden.
Die verknüpften Zeilen können dann normal durchsucht werden.

Aber da liegt es dann wahrscheinlich wieder an der Beschaffenheit der Daten.
Wenn EXISTS schon in der ersten Zeile abbricht, dann ist das natürlich schneller. Sollte aber tatsächlich jede Zeile diesen Daten-Unterschied haben, dann würde das bei den letzten Zeilen bedeuten, dass EXISTS für jede einzelne Zeile TABLEB jedes mal neu durchsuchen muss. Bei 10000 Zeilen und für jede Zeile ein Daten-Unterschied bedeutet das, dass im Schnitt pro Durchlauf etwas 5000 Zeilen, die durchsucht werden müssen. Zusammen gerechnet also 10000 mal 5000 Zeilen durchsuchen.
Das wäre der beste Fall, wenn für jede Zeile ein entsprechendes Ergebnis gefunden wird und EXISTS abbrechen kann.
Wird aber nichts gefunden, läuft die Suche bis zum Ende durch. Enthalten nur 1000 Zeilen den Unterschied, bedeutet das bei 10000 Zeilen, dass 9000 mal die ganze Tabelle durchsucht werden muss und 1000 mal teilweise. Nach der gleichen Rechnung wie oben und der Annahme, dass eine Zeile ihr Gegenstück auf der selben "Position" findet, dann bedeuten das, dass 9000 mal 10000 Zeilen durchsucht werden müssen und 1000 mal rund 500 Zeilen.

Ich kann mir nicht vorstellen, dass das irgendwie schneller sein könnte, als ein JOIN, der einmal komplett läuft und alle Zeilen einmal nach dem Index verknüpft.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Sa 23.08.14 21:30 
Zitat:
Ich kann mir nicht vorstellen, dass das irgendwie schneller sein könnte, als ein JOIN, der einmal komplett läuft und alle Zeilen einmal nach dem Index verknüpft.


Die Verknüpfung von Join und Exists funktioniert intern identisch (bis auf den Unterschied das exists frühzeitig abbrechen könnte, keine Ahnung welche DBs oder überhaupt eine das wirklich tun). Das was du für Join beschreibst gilt in gleichem Maße genauso für exists. Der Optimizer jeder Datenbank die ich kenne (zumindest der üblichen großen 3) wird das durch die gleichen Datenbanknahen Operationen identisch auflösen. Ob beim korrelieren zwischen den Tabellen dann ein Index verwendet wird hängt nicht vom SQL Operator ab sondern natürlich von den verwendeten korrelierten Feldern und der daraus zu erwarteten Größe der Ergebnismenge. Egal ob join oder exists.

Eigentlich sollte man immer wenn es nur um eine Existenzprüfung geht eher zu exists tendieren. Bei join kommt ja auf jedenfall noch der Aufwand hinzu potentielle mehrfache Treffer auszusieben (per Distinct oder Group By). Aber du kannst ja gerne beides mal gegeneinander antreten lassen (und danach auch den tatsächlichen Ausführungsplan beider SQLs vergleichen der vermutlich identisch ist). Beim SQL Server, DB2, Oracle wird exists gleichschnell oder schneller sein. Bei kleineren Desktopdatenbankensystemen ist das Spiel offener da würde ich selbst immer vorher erstmal die Alternativen durchprobieren.