Verkettung von Nicht-NULL-Werten einer Gruppe
15. November 2008 in Php / Mysql
GROUP_CONCAT(expr) verkettet alle Nicht-Null-Werte einer Gruppe und liefert einen String als Ergebnis zurück. Damit lassen sich Veranstaltungen finden, die beispielsweise mindestens den beiden Kategorien “Theater” und “Festivals” zugeordnet sind.
Angenommen wir besitzen die folgende Veranstaltungs-Kategorien-Tabelle:
-- -- Tabellenstruktur für Tabelle `events_categories` -- CREATE TABLE `events_categories` ( `eventId` int(11) unsigned NOT NULL, `categoryId` int(11) unsigned NOT NULL, PRIMARY KEY (`eventId`,`categoryId`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci; -- -- Daten für Tabelle `events_categories` -- INSERT INTO `events_categories` VALUES(1, 1); INSERT INTO `events_categories` VALUES(1, 2); INSERT INTO `events_categories` VALUES(1, 3); INSERT INTO `events_categories` VALUES(2, 1); INSERT INTO `events_categories` VALUES(3, 1); INSERT INTO `events_categories` VALUES(3, 2); INSERT INTO `events_categories` VALUES(4, 3);
Nun möchten wir gerne alle Events erhalten, die bei den Kategorien 1 und 2 eingetragen sind. Die Abfrage
SELECT * FROM `events_categories` WHERE `categoryId` IN ( 1, 2 )
liefert uns alle Veranstaltungen, die in mindestens einer der beiden Kategorien (Kategorie 1 oder Kategorie 2) eingetragen sind. Wir möchten aber nur jene, die in mindestens beiden eingetragen sind. Die Abfrage
SELECT eventId FROM `events_categories` WHERE `categoryId` IN ( 1, 2 )
GROUP BY eventId HAVING count( * ) = 2
erfüllt den Zweck. Wir erhalten die beiden Vernanstaltungs-Id´s 1 und 3. Schön und gut, aber die restlichen Kategorien bleiben verborgen. Wir können nun ein Subselect verwenden um an alle möglichen Infos ranzukommen.
SELECT * FROM events_categories WHERE eventId
IN (
SELECT eventId FROM `events_categories` WHERE `categoryId` IN ( 1, 2 )
GROUP BY eventId HAVING count( * ) = 2
)
Oder wir verwenden group_concat:
GROUP_CONCAT([DISTINCT]expr[,expr...] [ORDER BY {unsigned_integer|col_name|expr} [ASC | DESC] [,col_name...]] [SEPARATORstr_val])
SELECT eventId, group_concat( cast( categoryId AS char ) ) categories
FROM events_categories
GROUP BY eventId
HAVING find_in_set( '1', categories ) AND
find_in_set( '2', categories )
Viel Spass beim Austesten und Verbessern
