In einem Feld (in einem Beispiel id) sind Serien gespeichert. Alle aufeinander folgenden Nummern gelten als Serie.
CREATE TABLE test (`id` INT) ; INSERT INTO test (`id`) VALUES (1), (3), (4), (5), (7), (8), (10) ;
Das ganze soll dann so ausgegeben werden:
1 3-5 7-8 10
Heute kahm mir eine elgantere Lösung in den Sinn. Ich geh davon aus, dass sie auch schneller ist, da sie ohne Subselect im SELECT Teil auskommt. Die Logik ist umgedreht. statt vorwärts wird jetzt Rückwärts geschaut.
SELECT CASE WHEN MIN(prep.id) = MAX(prep.id) THEN MIN(prep.id) ELSE CONCAT(MIN(prep.id), '-', MAX(prep.id)) END AS id_range FROM ( SELECT @range_id := @range_id + IF(@last_id + 1 = t.id, 0, 1) AS range_id, @last_id := t.id AS id FROM -- Variablen deklarieren (SELECT @last_id := 0, @range_id:= 0) AS vars, (SELECT * FROM test ORDER BY id) AS t ) AS prep GROUP BY prep.range_id
Und hier mein Lösungsansatz
SELECT CASE WHEN MIN(prep.id) = MAX(prep.id) THEN MIN(prep.id) ELSE CONCAT(MIN(prep.id), '-', MAX(prep.id)) END AS id_range FROM ( SELECT -- Letzte Gruppe als GruppenId nehmen @group_id AS group_id, t.id, -- Nächte Gruppe ermitteln @group_id := CASE WHEN (t.id+1) NOT IN (SELECT id FROM test) THEN @group_id + 1 -- Die nexte ID exisitert nicht, ergo Gruppen-ID um eins erhöhen ELSE @group_id -- Due Gruppen-ID bleibt unverändert END AS next_group_id FROM (SELECT @group_id := 1) vars, test t ) prep GROUP BY prep.group_id;