======[MySQL] Serien gruppieren======
In einem Feld (in einem Beispiel id) sind Serien gespeichert. Alle aufeinander folgenden Nummern gelten als Serie.
===== Ausgangslage =====
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
===== Code neu =====
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
===== Code alt =====
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;
===== Spielwiese =====
*[[http://sqlfiddle.com/#!2/4d6ab2/1|Neues Beispiel bei sqlfiddle.com]]
*[[http://sqlfiddle.com/#!2/76b15/23|Altes Beispiel bei sqlfiddle.com]]
{{tag>MySQL}}