Объединение последовательных повторяющихся записей, включая временной диапазон - PullRequest
0 голосов
/ 11 мая 2018

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

Разница в том, что мне нужно, чтобы конечная дата была действительной, а не NULL.

Итак, учитывая следующие данные:

EmployeeId   StartDate   EndDate     Column1   Column2
1000         2009/05/01  2010/04/30   X         Y
1000         2010/05/01  2011/04/30   X         Y
1000         2011/05/01  2012/04/30   X         X
1000         2012/05/01  2013/04/30   X         Y
1000         2013/05/01  2014/04/30   X         X
1000         2014/05/01  2014/06/01   X         X

Желаемый результат:

EmployeeId   StartDate   EndDate     Column1   Column2
1000         2009/05/01  2011/04/30   X         Y
1000         2011/05/01  2012/04/30   X         X
1000         2012/05/01  2013/04/30   X         Y
1000         2013/05/01  2014/06/01   X         X

Предлагаемое решение в связанной ветке выглядит так:

with  t1 as  --tag first row with 1 in a continuous time series
(
select t1.*, case when t1.column1=t2.column1 and t1.column2=t2.column2
                  then 0 else 1 end as tag
  from test_table t1
  left join test_table t2
    on t1.EmployeeId= t2.EmployeeId and dateadd(day,-1,t1.StartDate)= t2.EndDate
)
select t1.EmployeeId, t1.StartDate, 
       case when min(T2.StartDate) is null then null
            else dateadd(day,-1,min(T2.StartDate)) end as EndDate,
       t1.Column1, t1.Column2
  from (select t1.* from t1 where tag=1 ) as t1  -- to get StartDate
  left join (select t1.* from t1 where tag=1 ) as t2  -- to get a new EndDate
    on t1.EmployeeId= t2.EmployeeId and t1.StartDate < t2.StartDate
 group by t1.EmployeeId, t1.StartDate, t1.Column1,   t1.Column2;

Однако, похоже, это не работает, когда вам нужна конечная дата, а не просто NULL.

Может ли кто-нибудь помочь мне с этим вопросом?

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Это еще одно решение (взято из Как группировать по непрерывным диапазонам ). Проще кодировать, а также обслуживать значения NULL (то есть обрабатывает NULL = NULL в отличие от простого сравнения LAG ()). Однако это может быть не так эффективно на больших объемах данных из-за GROUP BY

SELECT EmployeeId
,      MIN(StartDate) AS StartDate
,      MAX(EndDate)   AS EndDate
,      Column1 
,      Column2
FROM
(
    SELECT t.*
    ,      ROW_NUMBER() OVER(PARTITION BY EmployeeId, Column1, Column2 ORDER BY StartDate ) AS GRN
    ,      ROW_NUMBER() OVER(PARTITION BY EmployeeId                   ORDER BY StartDate ) AS RN
    FROM 
           test_table t
    ) t
GROUP BY
       EmployeeId
,      Column1 
,      Column2
,      RN - GRN
0 голосов
/ 11 мая 2018

Как насчет этого?

create table test_table (EmployeeId int, StartDate  date, EndDate  date,   Column1 char(1),  Column2 char(1))
;
insert into test_table values
 (1000    ,     '2009-05-01','2010-04-30','X','Y')
,(1000    ,     '2010-05-01','2011-04-30','X','Y')
,(1000    ,     '2011-05-01','2012-04-30','X','X')
,(1000    ,     '2012-05-01','2013-04-30','X','Y')
,(1000    ,     '2013-05-01','2014-04-30','X','X')
,(1000    ,     '2014-05-01','2014-06-01','X','X')
;
SELECT EmployeeId, StartDate, EndDate, Column1, Column2 FROM 
(
    SELECT EmployeeId, StartDate 
    ,      MAX(EndDate) OVER(PARTITION BY EmployeeId, RN) AS EndDate
    ,      Column1 
    ,      Column2
    ,      DIFF
    FROM
    (
        SELECT t.*
        ,      SUM(DIFF) OVER(PARTITION BY EmployeeId ORDER BY StartDate ) AS RN
        FROM
        (
            SELECT t.*
            ,      CASE WHEN
                       Column1 = LAG(Column1,1) OVER(PARTITION BY EmployeeId ORDER BY StartDate)
                   AND Column2 = LAG(Column2,1) OVER(PARTITION BY EmployeeId ORDER BY StartDate)
                   THEN 0 ELSE 1 END AS DIFF
            FROM
                test_table t
        ) t
    )
)
WHERE DIFF = 1
;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...