Vinzenz Mai: MySQL: GROUP BY, Aggregatsfunktionen + JOIN

Beitrag lesen

Hallo S.

ich möchte mit PHP / MYSQL einen Veranstaltungskalender realisieren.

welche MySQL-Version steht Dir zur Verfügung. Die Leistungsfähigkeit von MySQL unterscheidet sich zwischen einzelnen Versionen zum Teil dramatisch. Deswegen ist es bei MySQL-Fragen immer eine gute Idee, die vorhandene Version anzugeben.

Jedes Event kann an mehreren Locations stattfinden, und jede Location kann mehrere Events anbieten - oder denselben Event mehrmals.

tbl_events(
id,
name
)
tbl_locations(
id,
name
)
tbl_programm(
id,
event_id,
location_id
datum
)

Nun hätte ich unter anderem als Ergebnis einer Datenbankabfrage gern eine Liste der folgenden Form:

Event 1: Location A, Location B
Event 2. Location A, Location C, Location D

[...] PHP-Code [...]

Das finde ich aber ziemlich unschön. Vor allem wird für jeden Event eine neue Datenbankabfrage gestartet. Gibt es eine Möglichkeit, die Abfrage zu optimieren und eleganter, v.a. Ressourcen schonender zu demselben Ergebnis zu kommen?

Möglicherweise :-) Wenn Deine MySQL-Version die benötigte Funktionalität unterstützt.

Als erstes verbindest Du Deine drei Tabellen mit wunderschönen JOINS zu einer "Gesamttabelle". Falls Dir etwas dabei unklar sein sollte, lies bitte unsere Join-Artikel durch:

Einführung Joins
Fortgeschrittene Join-Techniken.

SELECT  
  e.name as Event,  
  l.name  
FROM tbl_events e  
INNER JOIN tbl_programm p  
ON e.id = p.event_id  
INNER JOIN tbl_locations l  
ON p.location_id = l.id  

Nun noch nach den Events gruppieren und die geeignete Aggregatsfunktion, nämlich GROUP_CONCAT() auf die Locations anwenden; beachte bitte die Hinweise in der Dokumentation zu dieser Funktion.

Folgender (ungetesteter) Code sollte Dir einen Einstieg in die Verwendung bieten:

SELECT  
  e.name as Event,  
  GROUP_CONCAT(  
    DISTINCT l.name  -- jede Location nur einmal  
    ORDER BY l.name  -- aufsteigend sortiert  
    SEPARATOR ', '   -- mit Komma und Leerzeichen getrennt  
  ) AS Locations     -- ein netter Spaltenname  
FROM tbl_events e  
INNER JOIN tbl_programm p  
ON e.id = p.event_id  
INNER JOIN tbl_locations l  
ON p.location_id = l.id  
GROUP BY e.name

Hättest Du das ganze gern aufsteigend nach dem ersten Datum eines Events sortiert, dann kommst Du um Subselects (Voraussetzung: MySQL 4.1 oder neuer) kaum herum.

Freundliche Grüße

Vinzenz