V této odpovědi budu předpokládat, že pole „id“ čísluje řádky postupně při řazení podle rostoucího data, jako je tomu v příkladech dat. (Takový sloupec lze vytvořit, pokud neexistuje).
Toto je příklad techniky popsané zde a zde .
1) Připojte tabulku k sobě na sousední hodnoty "id". Tím se spárují sousední řádky. Vyberte řádky, kde se pole "allocation" změnilo. Uložte výsledek do dočasné tabulky a udržujte také běžící index.
SET @idx = 0;
CREATE TEMPORARY TABLE boundaries
SELECT
(@idx := @idx + 1) AS idx,
a1.date AS prev_end,
a2.date AS next_start,
a1.allocation as allocation
FROM allocations a1
JOIN allocations a2
ON (a2.id = a1.id + 1)
WHERE a1.allocation != a2.allocation;
Získáte tak tabulku, která má v každém řádku „konec předchozího období“, „začátek dalšího období“ a „hodnotu „přidělení“ v předchozím období:
+------+------------+------------+------------+
| idx | prev_end | next_start | allocation |
+------+------------+------------+------------+
| 1 | 2012-01-01 | 2012-01-02 | 0 |
| 2 | 2012-01-02 | 2012-01-03 | 2 |
| 3 | 2012-01-05 | 2012-01-06 | 0 |
+------+------------+------------+------------+
2) Potřebujeme začátek a konec každé periody ve stejné řadě, takže musíme znovu spojit sousední řady. Udělejte to vytvořením druhé dočasné tabulky, jako je boundaries
ale mající idx
pole 1 větší:
+------+------------+------------+
| idx | prev_end | next_start |
+------+------------+------------+
| 2 | 2012-01-01 | 2012-01-02 |
| 3 | 2012-01-02 | 2012-01-03 |
| 4 | 2012-01-05 | 2012-01-06 |
+------+------------+------------+
Nyní se připojte na idx
pole a dostaneme odpověď:
SELECT
boundaries2.next_start AS start,
boundaries.prev_end AS end,
allocation
FROM boundaries
JOIN boundaries2
USING(idx);
+------------+------------+------------+
| start | end | allocation |
+------------+------------+------------+
| 2012-01-02 | 2012-01-02 | 2 |
| 2012-01-03 | 2012-01-05 | 0 |
+------------+------------+------------+
** Všimněte si, že tato odpověď dostane „interní“ období správně, ale chybí dvě „okrajová“ období, kde přidělení =0 na začátku a přidělení =5 na konci. Ty lze stáhnout pomocí UNION
klauzule, ale chtěl jsem prezentovat základní myšlenku bez této komplikace.