German SQL-Problem

Similar threads

B4A Tutorial SQL tutorial
B4A Tutorial [B4X] Smart String Literal
B4J Tutorial SQL Tutorial
B4A Question MSSQL-JDBC Minimalistic Example
B4A Library [B4X] BLE 2 - Bluetooth Low Energy
Hallo,

ich habe da ein kleines Problem mit einem SQL.Statement.

Ich habe 2 Tabellen:

B4X:
SQL1.ExecNonQuery("CREATE TABLE Bilder (IDx INTEGER PRIMARY KEY, bName TEXT ,bNr Integer, bDat TEXT, Jr Integer)")
SQL1.ExecNonQuery("CREATE TABLE Texte (IDx INTEGER PRIMARY KEY, eText TEXT ,tDat TEXT, TagText TEXT,D Integer,M Integer,J Integer, TNr Integer, DTag String)")
In der Tabelle Texte befindet sich die Spalte J. Diese beinhaltet die Jahreszahl
In der Spalte Bilder befindet sich die Spalte Jr. Diese beinhaltet ebenfalls die Jahreszahl.

Die IDx-Spalten vergibt die DB automatisch.

Den Datensatz in der Tabelle Texte gibt es maximal 1x pro Tag.
Die Datensätze in der Tabelle Bilder variieren. Es können pro Tag X Bilder hinzugefügt werden.

Nun wollte ich auswerten, wie viele Texte und Bilder pro Jahr gespeichert werden. Hier mein Code.

B4X:
    SQL="SELECT J, COUNT(T.IDx) As TAnz, COUNT(B.IDx) AS BAnz FROM Texte AS T LEFT JOIN Bilder AS B ON B.Jr = T.J GROUP BY J"
    C=SQL1.ExecQuery(SQL)

    For I=0 To C.RowCount-1
        C.Position=I
        E1=C.GetString("J")
        E2=C.Getint("TAnz")
        E3=C.Getint("BAnz")
        Log(E1 & "  " & E2 & "  " & E3)
    Next
Das Ergebnis ist z.B. für das Jahr:

2020 4440 4440
2019 9765 9765
2018 5828 5828
Das ist eindeutig falsch. Es gruppiert korrekt, aber Ich bekomme als Ergebnis Count(T.IDx) x COUNT(B.IDx)
Di Abfrage läuft problemlos durch. Es werden 3 Datensätze zurückgegeben. Das ist korrekt, da sich in der Datenbank die Jahre 2017, 2018 und 2019 befinden.
Es ist dabei egal ob ich COUNT(J) oder COUNT(IDx) nehme.

Ich bin mir sicher, dass meine Abfrage auf anderen DB-Systemen funktioniert.

Wo habe ich bei B4A einen Denkfehler?

Gruß Lothar
 

Alexander Stolte

Expert
Licensed User
Ich bin mir sicher, dass meine Abfrage auf anderen DB-Systemen funktioniert.
Nein, auch dort wird diese Abfrage nicht Funktionieren.
Weil du IDs doppelt zählst, um das zu vermeiden setze einfach ein "DISTINCT" davor.
Dies ist die richtige Abfrage:
B4X:
SELECT J, COUNT(DISTINCT T.IDx) As TAnz, COUNT(DISTINCT B.IDx) AS BAnz FROM Texte AS T LEFT JOIN Bilder AS B ON B.Jr = T.J GROUP BY J
B4X:
2017  11  11
2018  11  11
2019  8  18
Bilder = 40
Texte = 30
 
Hallo Alexander,

DANKE - Es funktioniert. Ich schäm mich. Das war es!
Mein Gedanke war, dass ich ja nicht IDs zähle, sondern Count(IDs) im Vergleich habe.
Habe aber dank Deiner Hilfe meine komplette Verirrung erkannt.

(Irgendwie habe ich aber trotzdem einen Knoten. Ich hätte DISTINCT nicht erkannt, da jeder IDx ja nur ein Mal da ist.)



Gruß Lothar
 

Alexander Stolte

Expert
Licensed User
Ich bin auch nur darauf gekommen, weil ich das in MySQL ganz oft so brauche, mein 1. Gedanke war dieser:
B4X:
SELECT J, COUNT(T.IDx) As TAnz,(SELECT COUNT(B.IDx) FROM Bilder WHERE Jr = T.J) AS BAnz FROM Texte AS T GROUP BY J
Das LEFT JOIN in eine eigene unterabfrage zu packen, aber gut das ich dann nochmal in meine Aufzeichnungen geschaut habe. ^^
 
Hallo Alexander,

die Select in eine Select zu packen ist meiner Meinung nach nicht eine so gute Lösung (In dem Fall)

Ich verwende ja explicit LEFT JOIN, da es ja (THEORETISCH) auch vorkommen kann, dass jemand gar keine Bilder speichert, sondern nur Text. In dem Fall bekäme er kein Ergebnis.

Gruß Lothar
(Danke für's Mitdenken)
 
Top