Mysql doppelte Zeilen vermeiden

Sprint

Erfahrenes Mitglied
Hallo zusammen,

erst einmal sorry für die blöde Überschrift. Mir ist nichts besseres eingefallen.

Zu meinem Problem. Ich habe hier zwei Tabellen, die eine beinhaltet verschiedene Schulungen, die andere die entsprechenden Teilnehmer:

Schulungen: kursid, typ, start
Teilnehmer: tid, kursid, anzahl, storniert

Für einen Buchungskalender werden die Kurse so abgefragt:

select distinct s.*, t.anzahl
from schulungen s
left join teilnehmer t on s.kursid = t.kursid and t.storniert = '0000-00-00 00:00:00'
where s.start between '$suchstart' and '$suchende'

Das funktioniert, solange ich keine oder nur eine Anmeldung für einen Termin habe. Wenn aber mehrere Anmeldungen für einen Kurs vorliegen, wird dieser Kurs entsprechend mehrfach ausgegeben. Das stört aber die anschließende Kalendererstellung.

So kann das z.B. aussehen:
kursidtypstartanzahl

[TR1][TD]2[/TD][TD]6[/TD][TD]2018-05-07[/TD][TD]NULL[/TD][/TR1]
[TR2][TD]7[/TD][TD]1[/TD][TD]2018-06-18[/TD][TD]5[/TD][/TR2]
[TR1][TD]8[/TD][TD]2[/TD][TD]2018-06-20[/TD][TD]2[/TD][/TR1]
[TR2][TD]8[/TD][TD]2[/TD][TD]2018-06-20[/TD][TD]1[/TD][/TR2]
[TR1][TD]11[/TD][TD]4[/TD][TD]2018-07-02[/TD][TD]NULL[/TD][/TR1]
[TR2][TD]-[/TD][TD]-[/TD][TD]-[/TD][TD]-[/TD][/TR2]
[TR1][TD]8[/TD][TD]2[/TD][TD]2018-06-20[/TD][TD]3[/TD][/TR1]

Wie man sieht, ist der Kurs mit der id 8 zwei Mal gebucht und wird entsprechend zwei Mal ausgegeben. Ich bräuchte aber eine Ausgabe wie in der letzten Zeile dargestellt, also nur eine Zeile mit addierter Anzahl.

Ist das irgendwie machbar oder muß ich das über php lösen?
Danke schon mal im Voraus,
Sprint
 
Moin Sprint,

versuch es so:
SQL:
select s.kurstyp, s.typ, s.start , t.anzahl
from schulungen s
left join (Select kursid, sum(t.anzahl) as Anzahl
    from teilnehmer
    where storniert = '0000-00-00 00:00:00' )
t on s.kursid = t.kursid
where s.start between '$suchstart' and '$suchende'
;

Grüße
Biber
 
Hallo Biber,

kann es sein, daß da was durcheinander gekommen ist? Egal was ich probiere bzw. ändere, ich bekomme in phpMyAdmin immer die Meldung "Für jede abgeleitete Tabelle muss ein eigener Alias angegeben werden".
 
Moin Sprint,

sorry, mein Fehler.

SQL:
SELECT s.kurstyp, s.typ, s.START , t.anzahl
FROM schulungen s
LEFT JOIN (SELECT kursid, SUM(anzahl) AS Anzahl
    FROM teilnehmer
    WHERE storniert = '0000-00-00 00:00:00' )
t ON s.kursid = t.kursid
WHERE s.START BETWEEN '$suchstart' AND '$suchende'
;

( es musste sum(anzahl) statt sum(t.anzahl) lauten)

Grüße
Biber
 
Hallo Biber,

jetzt funktioniert es zwar, allerdings werden jetzt ALLE Teilnehmer aus allen vorhandenen Kursen zusammengezählt und bei einem Eintrag ausgegeben. Wahrscheinlich habe ich mich da verkehrt ausgedrückt. Um bei der obigen Tabelle zu bleiben, müßte das korrekte Ergebnis so aussehen:

kursidtypstartanzahl

[TR1][TD]2[/TD][TD]6[/TD][TD]2018-05-07[/TD][TD]NULL[/TD][/TR1]
[TR2][TD]7[/TD][TD]1[/TD][TD]2018-06-18[/TD][TD]5[/TD][/TR2]
[TR1][TD]8[/TD][TD]2[/TD][TD]2018-06-20[/TD][TD]3[/TD][/TR1]
[TR2][TD]11[/TD][TD]4[/TD][TD]2018-07-02[/TD][TD]NULL[/TD][/TR2]

Es soll also zu jedem einzelnen Kurs die Gesamtanzahl der jeweiligen Teilnehmer ausgegeben werden. Wie eben bei Kurs 8, für den zwei Buchungen mit 1 bzw. 2 Teilnehmern vorliegen, zusammen also 3.
 
Ich habe es jetzt selbst geschafft, eine vermutliche Lösung hinzukriegen:

select s.*,
(select sum(t.anzahl) from teilnehmer t where t.kursid = s.kursid) as anzahl
from schulungen s
left join teilnehmer t on s.kursid = t.kursid and t.storniert = '0000-00-00 00:00:00'
where s.start between '$suchstart' and '$suchende'
group by s.kursid

Zumindest bekomme ich jetzt die richtigen Ergebnisse. Ob sich da noch ein Fehler drin versteckt hat, wird sich erst über die Zeit zeigen.
 
Moin Sprint,

sorry noch mal. Hab gestern wohl etwas unkonzentriert gepostet - in meiner Variante fehlte auch die entscheidende GROUP BY-Zeile.
SQL:
SELECT s.kurstyp, s.typ, s.START , t.anzahl
FROM schulungen s
LEFT JOIN (SELECT kursid, SUM(anzahl) AS Anzahl
    FROM teilnehmer
    WHERE storniert = '0000-00-00 00:00:00'
    GROUP BY kursid
)
t ON s.kursid = t.kursid
WHERE s.START BETWEEN '$suchstart' AND '$suchende'
;

Andererseits.... wenn du durch durch meine Schlamperei eine eigene Lösung suchen musstest und gefunden hast, hilft dir das eventuell mehr.

Grüße
Biber
 
Zurück