2015-08-19 23 views
5

Quello che sto cercando di fare è selezionare i periodi di tempo in cui il resto dei dati nella tabella era stabile in base a una colonna e controllare c'era un cambiamento nel valore della seconda colonna in questo periodo.SQL Server - Selezione dei periodi senza modifiche nei dati

Tabella:

create table #stable_periods 
(
[Date]    date, 
[Car_Reg]   nvarchar(10), 
[Internal_Damages] int, 
[External_Damages] int 
) 

insert into #stable_periods 
values ('2015-08-19', 'ABC123', 10, 10), 
     ('2015-08-18', 'ABC123', 9, 10), 
     ('2015-08-17', 'ABC123', 8, 9), 
     ('2015-08-16', 'ABC123', 9, 9), 
     ('2015-08-15', 'ABC123', 10, 10), 
     ('2015-08-14', 'ABC123', 10, 10), 
     ('2015-08-19', 'ABC456', 5, 3), 
     ('2015-08-18', 'ABC456', 5, 4), 
     ('2015-08-17', 'ABC456', 8, 4), 
     ('2015-08-16', 'ABC456', 9, 4), 
     ('2015-08-15', 'ABC456', 10, 10), 
     ('2015-01-01', 'ABC123', 1, 1), 
     ('2015-01-01', 'ABC456', NULL, NULL); 

--select * from #stable_periods 
-- Unfortunately I can’t post pictures yet but you get the point of how the table looks like 

Quello che vorrei ricevere è

Car_Reg \t FromDate \t ToDate \t   External_Damages Have internal damages changed in this period? 
 
ABC123 \t 2015-08-18 \t 2015-08-19 \t 10 \t    Yes 
 
ABC123 \t 2015-08-16 \t 2015-08-17 \t 9 \t    Yes 
 
ABC123 \t 2015-08-14 \t 2015-08-15 \t 10 \t    No 
 
ABC123 \t 2015-01-01 \t 2015-01-01 \t 1 \t    No 
 
ABC456 \t 2015-08-19 \t 2015-08-19 \t 3 \t    No 
 
ABC456 \t 2015-08-16 \t 2015-08-18 \t 4 \t    Yes 
 
ABC456 \t 2015-08-15 \t 2015-08-15 \t 10 \t    No 
 
ABC456 \t 2015-01-01 \t 2015-01-01 \t NULL \t    NULL

Fondamentalmente per costruire telai d'epoca in cui [External_Damages] erano costanti e di controllo ha fatto il [Internal_Damages ] cambia nello stesso periodo (non importa quante volte). Trascorro molto tempo a provare, ma temo che il mio livello di astrazione pensi in molto a basso ... Sarà fantastico vedere qualche suggerimento.

Grazie,

Bartosz

risposta

5

credo che questo sia una forma di Islands Problem.

Ecco una soluzione utilizzando ROW_NUMBER e GROUP BY:

SQL Fiddle

WITH CTE AS(
    SELECT *, 
     RN = DATEADD(DAY, - ROW_NUMBER() OVER(PARTITION BY Car_reg, External_Damages ORDER BY [Date]), [Date]) 
    FROM #stable_periods 
) 
SELECT 
    Car_Reg, 
    FromDate = MIN([Date]), 
    ToDate = MAX([Date]) , 
    External_Damages, 
    Change = 
      CASE 
       WHEN MAX(External_Damages) IS NULL THEN NULL 
       WHEN COUNT(DISTINCT Internal_Damages) > 1 THEN 'Yes' 
       ELSE 'No' 
      END  
FROM CTE c 
GROUP BY Car_Reg, External_Damages, RN 
ORDER BY Car_Reg, ToDate DESC 
+0

c'è qualche possibilità che possa gestire giorni mancanti nel set di dati? Supponendo che se nei periodi circostanti [External_Damages] sono uguali, allora saranno uguali in quei giorni mancanti e possiamo creare un periodo più lungo invece di poche interruzioni contenenti giorni mancanti nei dati? –

+0

@BartoszX, ti suggerisco di creare una nuova domanda per questo. –