SQL Server определяет время, превышающее порог - PullRequest
0 голосов
/ 01 ноября 2019

Я пытаюсь определить, сколько времени мои данные проводят выше определенного порога. У меня есть таблица значений SQL, которая выглядит следующим образом:

Data Image

Где первый столбец является datetime, а второй столбец является значением. Это данные временного ряда, поэтому это большая таблица, которую нельзя изменить. Я хочу знать первое значение, которое пересекает порог (скажем, 50 для примера), это мое начало, последнее значение, которое пересекает порог, являющийся концом, и продолжительность, потраченную на порог.

В моем примере данных Начало было бы 20.09.2009 19:18, конец - 20.09.2009 19:46, а продолжительность - 28 минут.

Это необходимо длябыть написано в одном заявлении sql из-за требований проекта. Мне просто интересно, возможно ли это и как это сделать. Спасибо!

1 Ответ

0 голосов
/ 01 ноября 2019

Вы можете использовать lead() и некоторую агрегацию:

select t.*
from (select t.*,
             datediff(minute,
                      ts, lead(ts) over (order by ts)
                     ) as diff_minutes
      from (select t.*,
                   lead(value) over (order by ts) as next_value
            from t
           ) t
      where (value < 50 and next_value >= 50) or
            (value >= 50 and next_value < 50
     ) t
where value < 50;

Ваш вопрос немного сложен, потому что вы хотите, чтобы промежуток времени начинался непосредственно перед рассматриваемым периодом. Это на самом деле упрощение. Вышеприведенные реализации:

  • Определение значения next .
  • Сохранение строки, когда значение next_value или текущее значение превышает пороговое значение или наоборот. Это первая строка до и последняя строка после периода.
  • Затем используйте lead(), чтобы получить конечную метку времени.
  • Наконец, отфильтруйте до первой строки.

Другой подход, возможно, проще. Определите группы на основе количества строк, которые ниже порог до или до строки. При этом предыдущая строка сохраняется со следующей группой.

Затем агрегируется:

select min(ts), max(ts),
       datediff(minute, min(ts), max(ts)) as diff_minute
from (select t.*,
             sum(case when value < 50 then 1 else 0 end) over (order by ts) as grp
      from t
     ) t
group by grp;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...