Datediff tra le righe non consecutive in una tabella
-
19-09-2019 - |
Domanda
Vorrei prendere la media della differenza di tempo da Table1 sotto. I valori non sono consecutivi e, occasionalmente, il valore di tempo viene ripetuta, quindi devono 1) In ordine di tempo, 2) eliminare valori non univoci, 3) eseguire la differenza di tempo (in millisecondi), quindi 4) media la differenza di tempo risultante valori. Inoltre mi piacerebbe 5) limitare l'operazione datediff ad un intervallo di tempo selezionato, come ad esempio DOVE _TimeStamp> = '20091220 11: 59: 56.1' E _TimeStamp <= _TimeStamp> = '20091220 11: 59: 56.8'. Sono abbastanza perplesso come mettere insieme tutto questo!
Tabella 1:
_TimeStamp
2009-12-20 11: 59: 56.0
2009-12-20 11: 59: 56.5
2009-12-20 11: 59: 56.3
2009-12-20 11: 59: 56.4
2009-12-20 11: 59: 56.4
2009-12-20 11: 59: 56.9
Soluzione
Ecco quello che funziona e non è brutto:
;WITH Time_CTE AS
(
SELECT
MIN(_Timestamp) AS dt,
ROW_NUMBER() OVER (ORDER BY MIN(_Timestamp)) AS RowNum
FROM Table1
GROUP BY _Timestamp
)
SELECT
t1.dt AS StartDate,
t2.dt AS EndDate,
DATEDIFF(MS, t1.dt, t2.dt) AS Elapsed
FROM Time_CTE t1
INNER JOIN Time_CTE t2
ON t2.RowNum = t1.RowNum + 1
Vi darà il seguente output dal vostro esempio:
StartDate | EndDate | Elapsed
------------------------+-------------------------+--------
2009-12-20 11:59:56.000 | 2009-12-20 11:59:56.300 | 300
2009-12-20 11:59:56.300 | 2009-12-20 11:59:56.400 | 100
2009-12-20 11:59:56.400 | 2009-12-20 11:59:56.500 | 100
2009-12-20 11:59:56.500 | 2009-12-20 11:59:56.900 | 400
Modifica:. Se si desidera limitare intervalli di tempo poi basta aggiungere WHERE _Timestamp BETWEEN @StartDate AND @EndDate
prima della riga GROUP BY
Edit2: E se si desidera che la media, quindi modificare questa affermazione SELECT t1.dt, ...
finale:
SELECT AVG(DATEDIFF(MS, t1.dt, t2.dt))
FROM Time_CTE t1 ... (same as above)
Altri suggerimenti
Fase 1 è quello di selezionare i tempi solo uniche:
SELECT DISTINCT _TimeStamp FROM table
WHERE _TimeStamp >= '20091220 11:59:56.1' AND _TimeStamp <= '20091220 11:59:56.8';
Quindi, se si vuole, ad esempio, confrontare tutti i tempi con l'altro (non so come si desidera selezionare volte), si potrebbe fare qualcosa di pazzo come:
SELECT t1._TimeStamp, t2._TimeStamp, DATEDIFF(ms,t1._TimeStamp,t2._TimeStamp) FROM
(SELECT DISTINCT _TimeStamp FROM table
WHERE _TimeStamp >= '20091220 11:59:56.1' AND _TimeStamp <= '20091220 11:59:56.8') AS t1
INNER JOIN
(SELECT DISTINCT _TimeStamp FROM table
WHERE _TimeStamp >= '20091220 11:59:56.1' AND _TimeStamp <= '20091220 11:59:56.8') AS t2
WHERE t1._TimeStamp != t2._TimeStamp;
La mia sintassi potrebbe essere spento, perché vengo da MySQL, ma qualcosa di simile dovrebbe funzionare.
Se si desidera che la media, si potrebbe provare a prendere la media dei risultati di cui sopra:
SELECT AVG(DATEDIFF(ms,t1._TimeStamp,t2._TimeStamp)) FROM
(SELECT DISTINCT _TimeStamp FROM table
WHERE _TimeStamp >= '20091220 11:59:56.1' AND _TimeStamp <= '20091220 11:59:56.8') AS t1
INNER JOIN
(SELECT DISTINCT _TimeStamp FROM table
WHERE _TimeStamp >= '20091220 11:59:56.1' AND _TimeStamp <= '20091220 11:59:56.8') AS t2
WHERE t1._TimeStamp != t2._TimeStamp;
Ancora non testati, ma in teoria, penso che dovrebbe funzionare.
Se le mie supposizioni su ciò che si vuole siano corretti, poi vedo due modi per farlo.
Il modo diretto:
SELECT
AVG(DATEDIFF(ms, T1.my_time, T2.my_time))
FROM
My_Table T1
INNER JOIN My_Table T2 ON
T2.my_time > T1.my_time
WHERE
NOT EXISTS
(
SELECT
*
FROM
My_Table T3
WHERE
(T3.my_time > T1.my_time AND T3.my_time < T2.my_time) OR
(T3.my_time = T1.my_time AND T3.my_pk < T1.my_pk) OR
(T3.my_time = T2.my_time AND T3.my_pk < T2.my_pk)
)
Il modo ingannevole:
SELECT
DATEDIFF(ms, MIN(my_time), MAX(my_time))/(COUNT(DISTINCT my_time) - 1)
FROM
My_Table
Dopo tutto, le differenze medie è solo la differenza totale diviso per il numero di divisioni in cui si sta scomponendola.
È necessario aggiungere clausole where per l'intervallo di date, se si desidera limitare da che e sarà necessario per tenere conto della possibilità di divisione per zero nella seconda query.