sql >> Database >  >> RDS >> Sqlserver

Groepen van opeenvolgende dagen maken die aan bepaalde criteria voldoen

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.



  1. Een datatabel invullen in C# met MySQL

  2. hasMany heeft gebeld met iets dat geen instantie is van Sequelize.Model

  3. Hoe kopieer je een mysql-tabel naar een andere in cakephp?

  4. Hoe een functie met Rowtype-parameter aan te roepen vanuit een select-instructie in Oracle