MySQLi -> Problem mit Abfrage (JOIN)

Wutaler

Mitglied
Hallo liebe Tutoren,

ich tüftle schon einige Stunden an einer Datenbankabfrage von 3 Tabellen gleichzeitig. Ich weiß das ich das irgendwie über LEFT JOIN oder ähnliche Anweisungen hinbekomme, aber es funktioniert nicht.

Ich habe folgende 3 Tabellen:

Haupttabelle mit den Usern
ID____UID
1_____XYZ
2_____ABC
3_____LMN

Zweite Tabelle mit bezahlten Beiträgen für das Jahr X
ID____UID____Jahr
1_____XYZ_____2011
2_____XYZ_____2013
3_____XYZ_____2017
4_____ABC_____2018


Dritte Tabbelle mit bezahlten Sonderbeiträgen für das Jahr X
ID____UID_____Jahr
1_____LMN_____2011
2_____XYZ _____2013
3_____LMN_____2015
4_____ABC_____2018
5_____LMN_____2017


(bitte die Unterstriche _ ignorieren, diese habe ich nur eingefügt um die prov. Tabellen besser zu formatieren)

ich möchte jetzt einen Hauptdatensatz aus der Haupttabelle auslesen und wenn vorhanden, den letzten zum User zugehörigen Beitrag und den letzten zum user zugehörigen Sonderbeitrag mit aufführen.

Am ende soll das etwa so aussehen:
User ABC ist aktiv. Letzter Beitrag 2018 und letzter Sonderbeitrag 2018
User XYZ ist aktiv. Letzter Beitrag 2017 und letzter Sonderbeitrag 2013
User LMN ist aktiv. Letzter Beitrag - und letzter Sonderbeitrag 2017


Jemand eine Idee?
 
SQL:
SELECT c.id, c.uid, jb.payYear FROM contracts c WHERE c.contractStatus IN ('1','2','3') INNER JOIN annual_subscription jb ON c.uid = jb.uid

Habe bisher erst einmal 2 Tabellen verbinden wollen, bevor ich mich an die dritte traue.

Nachtrag:
Habe die Spalte jb.YEAR in jb.payYear umbenannt, da YEAR eventuell konflikte auslösen könnte in der Abfrage
 
Okay, habe gerade nochmal ein wenig rumgespielt und dieses Beispiel erstellt. Es funktioniert auch erst einmal mit folgender Abfrage:
SQL:
SELECT c.id, c.uid, jb.payYear FROM contracts c INNER JOIN annual_subscription jb ON c.uid = jb.uid WHERE c.contractStatus IN ('1','2','3')

http://sqlfiddle.com/#!9/a2515/2

ABER... jetzt werden mir alle Datensätze angezeigt. Ich möchte ja nur aus der Haupttabelle alle datensätze einmal angezeigt bekommen und aus den nebentabellen jeweils den akuellsten, also quasi den letzten.
Er zeigt User 0004 auch nicht an, weil zu diesem user es in der zweiten Tabelle keine Daten gibt.
Da stehe ich auf dem Schlauch,schwierige abfrage
 
Es ist zwar keine elegante Lösung für ein allgemeines Problem bei der zweiten Tabelle den letzten Datensatz anzuzeigen, aber für meine Fälle reicht es MAX() zu verwenden, weil der letzte Datensatz immer das "höchste" Jahr ist...

Mit MAX(jb.payYear) funktioniert es tatsächlich...

Aber eventuell hat jemand ja noch eine gute Lösung wenn es sich mal nicht um Zahlen sondern texte handelt und man den neuesten Eintrag aus der zweiten Tabelle ziehen muss?!
 
Wutaler hat gesagt.:
Mit MAX(jb.payYear) funktioniert es tatsächlich...
Für die Nachwelt und weil ich gerade Lust hatte mit SQL zu experimentieren:
SQL:
SELECT Haupttabelle.ID, Haupttabelle.UID, 
FROM Haupttabelle h
LEFT JOIN Beiträge b ON
  b.UID = h.UID AND
  b.ID = (SELECT MAX(Jahr) FROM Beiträge WHERE UID = h.UID)

LEFT JOIN Sonderbeiträge s ON
  s.UID = h.UID AND
  s.ID = (SELECT MAX(Jahr) FROM Sonderbeiträge WHERE UID = h.UID)

Aktualisiertes Fiddle: http://sqlfiddle.com/#!9/a2515/27

Aber eventuell hat jemand ja noch eine gute Lösung wenn es sich mal nicht um Zahlen sondern texte handelt und man den neuesten Eintrag aus der zweiten Tabelle ziehen muss?!
Wie definierst du den neuesten Eintrag einer Tabelle? An sich ist eine Tabelle eine Menge von Tupeln, wenn du ihr eine Ordnung geben willst, so musst du dies manuell aus Anwendersicht tun (wie eben mit payYear). Sich auf DBMS-interne Details zu verlassen, ist gefährlich und unsauber ;) Genauso sich auf IDs zu verlassen.
 
Hallo ComFreek,

ja so ähnlich habe ich es auch gelöst.

Wie ich den neuesten Eintrag einer Tabelle definiere? Den mit dem höchsten AI-Wert (autoincrement)...

Aber mit MAX() hat es ja jetzt super funktioniert, danke für das Interesse und die Hilfe...
 
Zurück