Датифф между непослушающими рядами в таблице
-
19-09-2019 - |
Вопрос
Я хотел бы получить среднее значение разницы во времени из таблицы 1 ниже. Значения не являются последовательными, и иногда значение времени повторяется, поэтому мне нужно 1) сортировку по времени, 2) отказаться от неника ценности. Кроме того, я хотел бы 5) ограничить операцию датчика выбранным временным диапазоном, например, где _timestamp> = '20091220 11: 59: 56,1' и _timestamp <= _timestamp> = '20091220 11: 59: 56,8'. Я довольно озадачен, как собрать все это вместе!
Таблица 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
Решение
Вот тот, который работает и не уродлив:
;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
Даст вам следующий вывод из вашего примера:
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
РЕДАКТИРОВАТЬ: Если вы хотите ограничить диапазоны времени, просто добавьте WHERE _Timestamp BETWEEN @StartDate AND @EndDate
перед GROUP BY
линия.
Edit2: и если вы хотите среднего, тогда измените это окончательное SELECT t1.dt, ...
заявление к:
SELECT AVG(DATEDIFF(MS, t1.dt, t2.dt))
FROM Time_CTE t1 ... (same as above)
Другие советы
Шаг 1 - выбрать только уникальное время:
SELECT DISTINCT _TimeStamp FROM table
WHERE _TimeStamp >= '20091220 11:59:56.1' AND _TimeStamp <= '20091220 11:59:56.8';
Тогда, если вы хотите, скажем, сравнивайте все время друг с другом (не уверены, как вы хотите выбрать время), вы можете сделать что -то сумасшедшее, как:
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;
Мой синтаксис может быть отключен, потому что я прихожу из MySQL, но что -то подобное должно работать.
Если вы хотите среднего, вы можете попробовать получить среднее значение вышеуказанных результатов:
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;
Все еще не проверено, но теоретически, я думаю, что это должно работать.
Если мои предположения о том, что вы хотите, верны, то я вижу два способа сделать это.
Прямой путь:
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)
)
Сложный путь:
SELECT
DATEDIFF(ms, MIN(my_time), MAX(my_time))/(COUNT(DISTINCT my_time) - 1)
FROM
My_Table
В конце концов, средние различия - это всего лишь общая разница, деленная на количество подразделений, в которые вы ее разрушаете.
Вам нужно добавить, где положения для диапазона дат, если вы хотите ограничить это, и вам нужно будет учесть возможность разделения на ноль во втором запросе.