Мне нужно написать запрос, который показывает результат с разбивкой на FormID, которые имеют значение больше 5 на основе самого последнего LogDate.

Основываясь на самом последнем LogDate, если было значение меньше 5, оно должно отображать значения с этой точки, которые больше 5, поскольку значения под 5 являются «сбросом», если хотите.

Я в основном смотрю на недавние последовательные записи LogDate, которые больше 5.

Допустим, у нас есть следующий набор рекордов:

FormID   Value  LogDate    
--------------------------
Form2    6      10/12/19   
Form2    7      10/13/19   
Form1    8      10/12/19
Form1    12     10/12/19
Form1    3      10/14/19
Form1    8      10/15/19
Form1    6      10/21/19  

Следующее вернет следующее (обратите внимание, что я также хотел бы показать row_num:

 FormID   Value  LogDate   row_num
 ----------------------------------
 Form2    6      10/12/19  1
 Form2    7      10/13/19  2
 Form1    8      10/15/19  1
 Form1    6      10/21/19  2

Обратите внимание, что в приведенном выше примере, поскольку следующая запись имела недавнее значение меньше 5 (значение 3), нам нужно получить записи, которые больше 5.

Другой пример:

FormID   Value  LogDate     
Form1    8      10/15/19
Form1    3      10/21/19  

РЕЗУЛЬТАТ: Результаты не будут отображаться, так как в последней записи больше 5

Другой пример:

FormID   Value  LogDate    
Form2    4      10/12/19   
Form2    3      10/13/19   
Form1    16     10/12/19
Form1    3      10/12/19
Form1    3      10/14/19
Form1    8      10/15/19
Form1    12     10/21/19 

Результат здесь будет:

FormID   Value  LogDate   row_num
Form1    8      10/15/19  1
Form1    12     10/21/19  2

Другой пример:

FormID   Value  LogDate    
Form1    12      10/12/19   
Form2    13      10/13/19  

Результат:

FormID   Value  LogDate    row_num
Form1    12      10/12/19  1 
Form2    13      10/13/19  2

Насколько я понимаю, это можно сделать с помощью функции LAG, но я не знаю, как это сделать в целом.

Мы можем сделать что-то вроде следующего:

   DECLARE @mytable TABLE
   (
     FormID VARCHAR(50), 
     [Value] INT, 
     LogDate DATETIME
    )

    select t.*, 
        lag(value) over(partition by formid order by logdate) lag_value
    from @mytablet

Но не знаю, как все это собрать воедино.

1
Nate Pet 9 Ноя 2020 в 17:42

3 ответа

Лучший ответ

Если я правильно вас понял, вы можете сделать это с помощью таких оконных функций:

select 
from (
    select t.*, 
        row_number() over(partition by formid order by logdate desc) rn,
        sum(case when value > 5 then 1 else 0 end) over(partition by formid order by logdate desc) grp
    from mytable t
) t
where rn = grp

Идея состоит в том, чтобы сравнить количество значений выше 5 с номером строки, считая от самого последнего значения. Строки, в которых два значения равны, можно сохранить.

3
GMB 9 Ноя 2020 в 15:36

Найдите ориентировочный ответ в скрипке.

reset_calendar - это даты, когда произошел сброс, который используется для фильтрации данных.

SELECT temp.*,
       ROW_NUMBER() OVER (PARTITION BY temp.FormID ORDER BY temp.LogDate) AS Sequence
FROM (
  SELECT t.*
  FROM t
  LEFT JOIN (
    SELECT FormID, MAX(LogDate) AS recent_reset 
    FROM t
    WHERE Value<6
    GROUP BY FormID) AS reset_calendar
  ON t.FormID = reset_calendar.FormID
  WHERE t.LogDate > reset_calendar.recent_reset OR reset_calendar.recent_reset IS NULL)temp
1
JoPapou13 9 Ноя 2020 в 15:55

Один из методов:

select t.*,
       row_number() over (partition by formid order by logdate)
from t
where t.logdate > (select coalesce(max(t.logdate), '2000-01-01')
                   from t t2
                   where t2.formid = t.formid and t.value <= 5
                  );

Вы также можете использовать оконные функции:

select t.*,
       row_number() over (partition by formid order by logdate)
from (select t.*,
             max(case when value <= 5 then logdate end) over (partition by formid) as logdate_5
      from t
     ) t
where logdate_5 is null or
      date > logdate_5
order by formid, logdate;
1
Gordon Linoff 9 Ноя 2020 в 16:25