sql >> Databasteknik >  >> RDS >> Sqlserver

Skapa grupper av på varandra följande dagar som uppfyller ett givet kriterium

I det här svaret antar jag att "id"-fältet numrerar raderna i följd när de sorteras efter ökande datum, som det gör i exempeldata. (En sådan kolumn kan skapas om den inte finns).

Det här är ett exempel på en teknik som beskrivs här och här .

1) Förena tabellen med sig själv på intilliggande "id"-värden. Detta parar intilliggande rader. Välj rader där fältet "tilldelning" har ändrats. Lagra resultatet i en tillfällig tabell och behåll även ett löpande 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;

Detta ger dig en tabell med "slutet av föregående period", "början av nästa period" och "värdet av "tilldelning" i föregående period" på varje rad:

+------+------------+------------+------------+
| 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) Vi behöver början och slutet av varje period i samma rad, så vi måste kombinera intilliggande rader igen. Gör detta genom att skapa en andra temporär tabell som boundaries men har en idx fält 1 större:

+------+------------+------------+
| 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 |
+------+------------+------------+

Gå nu med på idx och vi får svaret:

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 |
+------------+------------+------------+

** Observera att detta svar får de "interna" perioderna korrekt men missar de två "kant"-perioderna där allokering =0 i början och allokering =5 i slutet. De kan dras in med UNION klausuler men jag ville presentera kärnidén utan den komplikationen.



  1. Ordna efter maxvärde i tre olika kolumner

  2. MySQL-fråga med JOIN som inte använder INDEX

  3. SQL-fel:ORA-14006:ogiltigt partitionsnamn

  4. Sortera data (ordning efter) före grupp efter i mysql