AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Self join und Abs()

Ein Thema von semo · begonnen am 29. Aug 2011 · letzter Beitrag vom 30. Aug 2011
Antwort Antwort
Benutzerbild von semo
semo

Registriert seit: 24. Apr 2004
755 Beiträge
 
Delphi 2010 Professional
 
#1

Self join und Abs()

  Alt 29. Aug 2011, 23:08
Datenbank: SQLite • Version: 3.26 • Zugriff über: AnyDAC
Ich möchte Geldflüsse nachvollziehen.
Ein Beispiel: am 01.10. wurden 100 € von einem Konto überwiesen und am 03.10 sind diese auf einem anderen Konto eingegangen und dort wiederum weiter überwiesen worden.
Nun muss ich ja hier den Betrag 100 € und -100 € abfragen und auch den Zeitraum der Buchungen berücksichtigen. Als Beispiel habe ich mal 7 Tage angesetzt.

Aufbau meiner Tabelle "Buchungen", die alle Buchungen aller Konten enthält:
Code:
ID
KontoID
Buchungstag
Geldbetrag
Verwendungszweck
Kontonummer
Bankleitzahl
Bemerkungen
Mein bisheriger Lösungansatz:
Code:
select
b1.id,
b1.KontoID,
b1.Buchungstag,
b1.geldbetrag,
Abs(b1.geldbetrag) as b1absgeldbetrag,
b1.Verwendungszweck,
b1.Kontonr,
b1.BLZ,
b1.Bemerkung,
b2.id,
b2.Buchungstag,
b2.Geldbetrag,
Abs(b2.Geldbetrag) as b2absgeldbetrag
FROM Buchungen b1, Buchungen b2
WHERE
b1absgeldbetrag = b2absgeldbetrag
and b1.id <> b2.id
and b1.buchungstag between b2.Buchungstag - 7 and b2.buchungstag
Die Abfrage läuft ewig. Ist der join zweier Tabellen per berechnetem Wert (Abs()) erlaubt?
Hat jemand Verbesserungsvorschläge für mich?

Geändert von semo (29. Aug 2011 um 23:32 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: Self join und Abs()

  Alt 29. Aug 2011, 23:17
Schreib doch mal auf

a) was in den Tabellen stehen wird (die Daten)
Und
b) was die Abfrage liefern soll
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
FredlFesl

Registriert seit: 19. Apr 2011
293 Beiträge
 
Delphi 2009 Enterprise
 
#3

AW: Self join und Abs()

  Alt 30. Aug 2011, 07:47
Die Abfrage läuft ewig. Ist der join zweier Tabellen per berechnetem Wert (Abs()) erlaubt?
Erlaubt ist alles, was nicht verboten ist. Wieso sollte das verboten sein?

Aber SQLite ist nicht gerade Performanceweltmeister.

Falls ID monoton steigend ist, würde ich die Abfrage zusätzlich mit "a.ID > b.ID" einschränken.
Welche Spalten sind mit einem Index versehen?

Wenn Du ausgehende (<0) mit eingehenden (>0) Buchungen korrelieren willst, würde ich nicht mit ABS arbeiten, sondern die Buchungswerte direkt vergleichen. Das ist genauer, denn deine Abfrage liefert auch die Buchungen, bei denen ein Geldbetrag X auf ein Konto Y eingegangen ist, und der gleiche Betrag bis zu 7 Tage später irgendwo abgegangen ist => Blödsinn.
SQL-Code:
Select * from
  buchungen as Ausgehend join
  buchungen as Eingehend
    on Ausgehend.Geldbetrag = -Eingehend.Geldbetrag -- Index kann nicht verwendet werden!

where Eingehend.ID>Ausgehend.ID
  and Ausgehend.Geldbetrag < 0
  and Eingehend.Buchungsdatum between Ausgehend.Buchungsdatum - 7 and Ausgehend.Buchungsdatum
Du könntest auch den Geldbetrag als Absolutwert speichern und ein zusätzliches Feld "BuchungsArt" einführen. Dort steht dann "Überweisung", "Einzahlung" etc. drin.
Darüber (und über den Geldbetrag) legst Du dann einen Index und verwendest diese Spalten als JOIN-Verknüpfung. Dann kann die DB die Indexe verwenden. So ist das nicht möglich und daher wird die Abfrage recht langsam sein.

SQL-Code:
Select * from
  buchungen as Ausgehend join
  buchungen as Eingehend
    on Ausgehend.Geldbetrag = Eingehend.Geldbetrag -- Index kann verwendet werden!

where Eingehend.ID>Ausgehend.ID
  and Ausgehend.Buchungsart = Ueberweisung
  and Eingehend.Buchungsart = Einzahlung
  and Eingehend.Buchungsdatum between Ausgehend.Buchungsdatum - 7 and Ausgehend.Buchungsdatum
Oder machst es noch anders:
Du führst zwei Spalten für den Geldbetrag: Ausgehend, Eingehend. Darüber legst Du jeweils einen Index und vergleichest dann Ausgehend mit Eingehend.

SQL-Code:
Select * from
  buchungen as Ausgehend join
  buchungen as Eingehend
    on Ausgehend.AusgehenderGeldbetrag = Eingehend.EingehenderGeldbetrag -- Index kann verwendet werden

where Eingehend.ID>Ausgehend.ID
  and Ausgehend.AusgehenderGeldbetrag < 0
  and Eingehend.Buchungsdatum between Ausgehend.Buchungsdatum - 7 and Ausgehend.Buchungsdatum
Das Bild hängt schief.
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.737 Beiträge
 
Delphi 6 Enterprise
 
#4

AW: Self join und Abs()

  Alt 30. Aug 2011, 08:46
Da ich alles andere als ein Banker bin, mal naiv gefragt. Würde es nicht Sinn machen auch den "Zweck" in den Vergleich mit aufzunehmen, da der doch bei der Abgehenden und Ankommenden Buchun gleich sein müsste, oder?
Ralph
  Mit Zitat antworten Zitat
Benutzerbild von semo
semo

Registriert seit: 24. Apr 2004
755 Beiträge
 
Delphi 2010 Professional
 
#5

AW: Self join und Abs()

  Alt 30. Aug 2011, 08:47
Es geht darum Geldschiebereien über mehrere Konten hinweg nachzuvollziehen und nicht nur die korrespondierenden Eingänge auf einem Konto nach einer Überweisung von einem anderen Konto anzuzeigen.

Angezeigt werden sollen alle Geldflüsse gruppiert nach Betrag, so dass interessante Konten dabei zum Vorschein kommen.

Geändert von semo (30. Aug 2011 um 08:53 Uhr)
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#6

AW: Self join und Abs()

  Alt 30. Aug 2011, 09:19
-Du solltest zunächst einen sauberen Join hinbekommen.
Andernfalls permutieren die Mengen und Du erhältst keinen Geldstrom, sondern eine wunderbare Geldvermehrung.
- Dann wäre zu klären, ob es ein geschlossenes Kontensystem ist oder nicht und wie Du dann die Einzelbuchungen "nach innen" und "nach außen" bearbeitest und bewertest.
- Und was ist ein "Geldstrom"? Deine Abfrage stellt scheinbar einfach ein Buchungspaar nebeneinander.

Der "größer" Vergleich und der Betragsjoin hinken ziemlich. Was ist mit identischen Beträgen im Betrachtungszeitraum? Die werden bei dem Statement alle (jeder mit jedem ) gejoint! Hast Du Kontrolle über das Verfahren, mit dem die Buchungen erzeugt werden? Das würde evtl. einen Ansatzpunkt über die ID liefern. Wenn die Buchungsoperation 100% atomar ist und eine ordentliche sequenz verwendet wird und später niemand in den Daten "rumfummelt", müsstest Du Buchungspaare an aufeinanderfolgenden ID erkennen und joinen können. Auch der Verwendungszweck könnte ein Kriterium sein. Der sollte zumindest für ein Buchungspaar identisch sein, eindeutiges Joinkriterium wäre er aber auch nicht.

Wenn der Join exakt ist (nicht mehr permutiert) wirst Du schon einen Performance Unterschied bemerken. Dann kannst Du mit Tuning beginnen: Indizes, Queryumstellung, Optimizerregeln (gibts die unter SQLite?)

Grundsätzlich wäre noch die Frage, ob Du nur auswerten willst/kannst oder ob Du auch Einfluss auf das Datenmodel hast.

OT: Monopoly gibt es schon als Computerspiel
Gruß, Jo
  Mit Zitat antworten Zitat
Benutzerbild von semo
semo

Registriert seit: 24. Apr 2004
755 Beiträge
 
Delphi 2010 Professional
 
#7

AW: Self join und Abs()

  Alt 30. Aug 2011, 21:15
Ich habe nun erst einmal alle Buchungen nach dem absoluten Betrag gruppiert:
Code:
select * FROM Buchungen as b1
where
b1.Geldbetrag <> 0
and
Abs(b1.Geldbetrag) in
(
SELECT Abs(b2.Geldbetrag) as b2absbetrag
FROM Buchungen b2
where b2absbetrag <> 0
GROUP BY b2absbetrag
HAVING count(b2absbetrag) > 1
)
order by Abs(b1.Geldbetrag) desc, b1.Buchungstag asc
Dies geht recht fix und man hat nun zumindest mal eine Grundlage für die manuelle Auswertung.
Jetzt fehlt "nur" noch die Abfrage der Buchungen innerhalb eines Zeitraums von zum Beispiel 7 Tagen.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:13 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz