Определить изменение столбца по строке - PullRequest
0 голосов
/ 12 февраля 2020

Прежде всего, я действительно искал похожий код, но я не нашел ничего подходящего.

Что я хочу сделать, это показать строки, когда employee_type_id изменяется для каждого сотрудника, перечисляя employee_id , дата от и последний date_to для основного ответа Идентификатор сотрудника .

Я пытался с разделением и функцией задержки, но мне не удалось решить эту проблему.

Любая помощь приветствуется.

У меня есть это:

employee_id   Date_From               Date_To                 EMPLOYEE_TYPE_ID
----------- ----------------------- ----------------------- ----------------
11223344      2016-11-07 00:00:00.000 2016-12-11 00:00:00.000 1
11223344      2016-12-12 00:00:00.000 2016-12-31 00:00:00.000 1
11223344      2017-01-01 00:00:00.000 2017-04-28 00:00:00.000 38
11223344      2017-04-29 00:00:00.000 2017-06-30 00:00:00.000 38
11223344      2017-07-01 00:00:00.000 2017-11-30 00:00:00.000 1
11223344      2017-12-01 00:00:00.000 2018-01-04 00:00:00.000 38
...
22233344      2012-06-01 00:00:00.000 2012-10-31 00:00:00.000 1
22233344      2012-11-01 00:00:00.000 2014-02-28 00:00:00.000 1
22233344      2017-12-01 00:00:00.000 2018-01-04 00:00:00.000 39
22233344      2018-01-05 00:00:00.000 2018-03-09 00:00:00.000 2

и это то, что я пытаюсь добиться:

employee_id   Date_From              EMPLOYEE_TYPE_ID
----------- -----------------------  ----------------
11223344      2016-11-07 00:00:00.000 2016-12-31 00:00:00.000 1
11223344      2017-01-01 00:00:00.000 2017-06-30 00:00:00.000 38
11223344      2017-07-01 00:00:00.000 2017-11-30 00:00:00.000 1
11223344      2017-12-01 00:00:00.000 2018-01-04 00:00:00.000 38
...
22233344      2012-06-01 00:00:00.000 2014-02-28 00:00:00.000 1
22233344      2017-12-01 00:00:00.000 2018-01-04 00:00:00.000 39
22233344      2018-01-05 00:00:00.000 2018-03-09 00:00:00.000 2

Ответы [ 2 ]

1 голос
/ 12 февраля 2020

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

select employee_id, EMPLOYEE_TYPE_ID,
       date_from,
       coalesce(dateadd(day, -1, lead(date_from) over (partition by emplyee_id order by date_from),
                max_date_to
               ) as date_to
from (select t.*,
             lag(EMPLOYEE_TYPE_ID) over (partition by employee_id order by date_from) as prev_et,
             max(date_to) over (partition by employee_id) as max_date_to
      from t
     ) t
where prev_et is null or prev_et <> EMPLOYEE_TYPE_ID;

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

1 голос
/ 12 февраля 2020

Как прокомментировал Time Biegeleisen, это типичная проблема разрывов и островков. Вы хотите сгруппировать «смежные» строки, которые имеют одинаковые employee_id и employee_type_id.

Вот один из способов решить это с помощью оконных функций:

select
    employee_id,
    min(date_from) date_from,
    max(date_to) date_to,
    employee_type_id
from (
    select
        t.*,
        row_number() over(partition by employee_id order by date_from) rn1,
        row_number() over(partition by employee_id, employee_type_id order by date_from) rn2
    from mytable t
) t
group by employee_id, employee_type_id, rn1 - rn2

Внутренний запрос ранжирует записи по двум различным разделам (на сотрудника и на сотрудника и типа). Когда разница между номерами строк изменяется, запускается новый остров (вы можете запустить подзапрос независимо и увидеть результат, который он выдает). Затем внешний запрос просто агрегирует по группам.

...