Сохраняйте строку для каждого изменения в столбце (включая NULL) в SQL Server - PullRequest
0 голосов
/ 16 июня 2020

Я хочу отслеживать изменения в наборе данных на SQL сервере.

В настоящее время у меня есть данные, похожие на эти

    Unique Ref  FromDate    ToDate     Status
           1    01/01/2020  03/01/2020  A
           1    03/01/2020  03/02/2020  NULL
           1    03/02/2020  04/04/2020  B
           1    04/04/2020  05/04/2020  B
           1    05/04/2020  06/06/2020  A
           2    03/01/2020  05/01/2020  NULL
           2    05/01/2020  06/07/2020  B
           2    06/07/2020  07/07/2020  B
           2    07/07/2020  08/07/2020  A

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

Пытаюсь сделать так, чтобы вышеперечисленное выглядело

Unique Ref  Status  ChangedDate
         1  A       01/01/2020
         1  NULL    03/01/2020
         1  B       03/02/2020
         1  A       05/04/2020
         2  NULL    03/01/2020
         2  B       05/01/2020
         2  A       07/07/2020

Я никогда не делал ничего подобного раньше, поэтому не уверен, с чего начать.

1 Ответ

1 голос
/ 16 июня 2020

Используйте lag(). Я думаю, что это делает то, что вы хотите:

select t.ref, t.status, t.fromDate as changedDate
from (select t.*,
             lag(status) over (partition by ref order by fromDate) as prev_status,
             row_number() over (partition by ref order fromDate) as seqnum
      from t
     ) t
where prev_status <> status or
      prev_status is null and status is not null or
      prev_status is not null and status is null or
      seqnum = 1;

Значения NULL усложняют задачу. Последнее условие обрабатывает случай, когда первая строка для ссылки NULL.

Я думаю, что другой подход немного проще:

select t.ref, t.status, t.fromDate as changedDate
from (select t.*,
             lag(fromDate) over (partition by ref order by fromDate) as prev_date,
             lag(fromDate) over (partition by ref, status order by fromDate) as prev_status_date
      from t
     ) t
where prev_status_date is null or
      prev_status_date <> prev_date;

Это просто сравнивает предыдущую дату для статус на предыдущую дату для записи в целом.

...