In dit antwoord ga ik ervan uit dat het veld "id" de rijen opeenvolgend nummert wanneer gesorteerd op oplopende datum, zoals in de voorbeeldgegevens. (Zo'n kolom kan worden gemaakt als deze niet bestaat).
Dit is een voorbeeld van een techniek die hier wordt beschreven en hier .
1) Voeg de tabel toe aan zichzelf op aangrenzende "id"-waarden. Dit koppelt aangrenzende rijen. Selecteer rijen waar het veld "toewijzing" is gewijzigd. Sla het resultaat op in een tijdelijke tabel en houd ook een lopende index bij.
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;
Dit geeft u een tabel met "het einde van de vorige periode", "het begin van de volgende periode" en "de waarde van 'toewijzing' in de vorige periode" in elke rij:
+------+------------+------------+------------+
| 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) We hebben het begin en einde van elke periode in dezelfde rij nodig, dus we moeten aangrenzende rijen opnieuw combineren. Doe dit door een tweede tijdelijke tabel te maken, zoals boundaries
maar met een idx
veld 1 groter:
+------+------------+------------+
| 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 |
+------+------------+------------+
Doe nu mee op de idx
veld en we krijgen het antwoord:
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 |
+------------+------------+------------+
** Merk op dat dit antwoord de "interne" perioden correct krijgt, maar de twee "edge" perioden mist waarbij toewijzing =0 aan het begin en toewijzing =5 aan het einde. Die kunnen binnengehaald worden met UNION
clausules, maar ik wilde het kernidee presenteren zonder die complicatie.