Соберите все строки, у которых есть изменения в каком-либо столбце в течение интервала дат - PullRequest
0 голосов
/ 31 августа 2018

У меня есть таблица истории, которая содержит журнал истории изменений для целевого объекта, и я хочу выбрать строки, значения которых были изменены в течение некоторого периода времени.

Пример данных:

TargetId  Value  CreatedUtcDateTime 
1         1      2018-03-09
1         1      2018-04-09
1         2      2018-04-10
2         3      2018-05-10
2         4      2018-06-10
2         5      2018-07-10
3         4      2017-08-10
3         1      2018-09-12
3         2      2018-10-13

Ожидаемый результат для интервала от '2018-01-01' до '2019-02-01':

TargetId OldValue NewValue CreatedUtcDateTime 
1        1        2        2018-04-10
2        3        4        2018-06-10
2        4        5        2018-07-10
3        4        1        2018-09-12
3        1        2        2018-10-13

До сих пор я придумал решение, основанное на функциях Windows:

select c1.TargetId as Coil, 
       c2.Value as OldValue, 
       c1.Value as NewValue, 
       c1.CreatedUtcDateTime as ChangeDate
from (select ROW_NUMBER() over (partition by TargetId order by CreatedUtcDateTime) as rowNum, 
     TargetId, 
     Value, 
     CreatedUtcDateTime  from History) c1
join ( select ROW_NUMBER() over (partition by TargetId order by CreatedUtcDateTime) as rowNum, 
              TargetId, 
              Value, 
              CreatedUtcDateTime 
         from History) c2
  on c1.rowNum = c2.rowNum + 1 
 and c1.TargetId = c2.TargetId 
 and c1.Value != c2.Value 
 and c1.CreatedUtcDateTime > c2.CreatedUtcDateTime
 where c1.CreatedUtcDateTime > '2018-01-01' 
   and c1.CreatedUtcDateTime < '2019-02-01'

Но это производит два полных сканирования таблицы, и я хочу избежать этого. Есть ли более эффективный способ добиться этого?

1 Ответ

0 голосов
/ 31 августа 2018

Вы можете использовать lag():

select h.*
from (select h.*, lag(value) over (partition by targetId order by CreatedUtcDateTime) as old_value
      from history h
     ) h
where CreatedUtcDateTime >= '2018-01-01' and
      CreatedUtcDateTime < '2019-02-01' and
      old_value <> value;  -- I can't tell if this is necessary

Важным моментом является то, что временная фильтрация выполняется во внешнем запросе, а не во внутреннем. В противном случае вы пропустите первое изменение за период.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...