Проверка критериев датировки между каждым значением для пользователя - PullRequest
0 голосов
/ 13 сентября 2018

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

id   rank   onboarded_at   applied_at   
A    1      1/1/2018       1/2/2018     
A    2      1/1/2018       2/3/2018     
A    3      1/1/2018       3/4/2018     
B    1      2/1/2018       null        
B    2      2/1/2018       8/1/2018     
C    1      3/1/2018       4/1/2018     
C    2      3/1/2018       7/1/2018     
C    3      3/1/2018       8/1/2018    

Я могу рассчитать lapsed_now, если между> 1) onboarded_at и current_date (если нет applied_at)> 12 недель (т.е. 84 дня)существует), 2) max(applied_at) и current_date.

Рассчитывается так:

case when max(applied_at) over (partition by id) is null and current_date - 84 > onboarded_at::date then 1
when current_date - 84 > max(applied_at) over (partition by id)::date and onboarded_at < max(applied_at) over (partition by id) then 1 else 0 end lapsed_now

Вывод:

id   rank   onboarded_at   applied_at   lapsed_now
A    1      1/1/2018       1/2/2018     1
A    2      1/1/2018       2/3/2018     1
A    3      1/1/2018       3/4/2018     1 
B    1      2/1/2018       null         0
B    2      2/1/2018       8/1/2018     0 --not lapsed now
C    1      3/1/2018       4/1/2018     0
C    2      3/1/2018       7/1/2018     0
C    3      3/1/2018       8/1/2018     0 --not lapsed now

Однако хотелось быаналогичным образом вычислить столбец id level lapsed_ever, где мы добавляем эти 2 дополнительных условия к lapsed_now:

1) Если для получения первого applied_at потребовалось> 84 дня (независимо от того, есть лиapplied_at в течение 84 дней спустя)

2) Если для идентификатора потребовалось> 84 между ЛЮБОЙ из applied_at (каждый заявленный имеет ранг +1)

Как я могу это сделать?Это будет вывод - где B равно lapsed_ever из-за того, сколько времени потребовалось, чтобы получить первые applied_at, а C равно lapsed_ever из-за того, сколько времени потребовалось, чтобы получить от rank=1 до rank=2:

id   rank   onboarded_at   applied_at   lapsed_now   lapsed_ever
A    1      1/1/2018       1/2/2018     1            0           
A    2      1/1/2018       2/3/2018     1            0
A    3      1/1/2018       3/4/2018     1            0
B    1      2/1/2018       null         0            1 --lapsed
B    2      2/1/2018       8/1/2018     0            1
C    1      3/1/2018       4/1/2018     0            1
C    2      3/1/2018       8/1/2018     0            1 --lapsed
C    3      3/1/2018       9/1/2018     0            1

Для условия # 1 я думаю, что могу сделать: case when datediff(day, onboarded_at, min(applied_at) over (partition by id))>84 then 1 Но не уверен, что делать для # 2

---- EDIT ---- Согласно ответу @ Джима, этопохоже, это мой вывод:

id  rank    onboarded_at    applied_at  lapsed_now  lapsed_date
A   1       1/1/2018        1/2/2018    1           (null)
A   2       1/1/2018        2/3/2018    1           (null)
A   3       1/1/2018        3/4/2018    1           (null)
B   1       2/1/2018        (null)      0           10/24/2018 
B   2       2/1/2018        8/1/2018    0           10/24/2018 
C   1       3/1/2018        4/1/2018    0           11/24/2018 
C   2       3/1/2018        8/1/2018    0           11/24/2018 
C   3       3/1/2018        9/1/2018    0           11/24/2018 

Однако, это должно быть:

id  rank    onboarded_at    applied_at  lapsed_now  lapsed_date
A   1       1/1/2018        1/2/2018    1           5/27/2018
A   2       1/1/2018        2/3/2018    1           5/27/2018
A   3       1/1/2018        3/4/2018    1           5/27/2018 (March 4 + 84)
B   1       2/1/2018        (null)      0           4/26/2018 (Feb 1 + 84)
B   2       2/1/2018        8/1/2018    0           4/26/2018
C   1       3/1/2018        4/1/2018    0           6/24/2018 
C   2       3/1/2018        8/1/2018    0           6/24/2018 (Apr 1 + 84)
C   3       3/1/2018        9/1/2018    0           6/24/2018 

1 Ответ

0 голосов
/ 17 сентября 2018

Похоже, что два упомянутых вами случая фактически совпадают.Вы хотите знать, прошло ли 84 дня когда-либо для каждого идентификатора.Вы можете сделать это с помощью следующего:

CREATE TABLE dbo.Onboarded
(
  id VARCHAR(10),
  rank INTEGER,
  onboarded_at DATE,
  applied_at DATE
  );

INSERT INTO dbo.Onboarded VALUES
('A',1,'20180101','20180102'),
('A',2,'20180101','20180203'),
('A',3,'20180101','20180304'),
('B',1,'20180201',NULL),
('B',2,'20180201','20180801'),
('C',1,'20180301','20180401'),
('C',2,'20180301','20180801'),
('C',3,'20180301','20180901');

SELECT onb.[id],
onb.[rank],
onb.[onboarded_at],
onb.[applied_at],
onb.[lapsed_now],
CASE WHEN [lapsed_now] = 1 OR [lapsed_previous] = 1
    THEN 1
    ELSE 0
END [lapsed_ever],
CASE WHEN lapsed_now = 1
    THEN DATEADD(DAY, 84, [lapsed_now_date])
    ELSE [min_applied_at_add_84]
END [lapsed_date]
FROM
(SELECT *,
CASE
    WHEN DATEDIFF(DAY, onboarded_at, MIN(ISNULL(applied_at, onboarded_at)) over (PARTITION BY id ORDER BY rank ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) >= 84
        THEN 1
    WHEN DATEDIFF(DAY, MAX(applied_at) OVER (PARTITION BY id ORDER BY rank ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING), GETDATE()) >= 84
        THEN 1
    ELSE 0
END [lapsed_now],
CASE
    WHEN MAX(DATEDIFF(DAY, onboarded_at, ISNULL(applied_at, GETDATE()))) OVER (PARTITION BY id ORDER BY rank ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) >= 84
        THEN 1
    ELSE 0
END [lapsed_previous],
MAX(applied_at) OVER (PARTITION BY id ORDER BY rank ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) [lapsed_now_date],
DATEADD(DAY, 84, MIN(CASE WHEN applied_at IS NULL THEN onboarded_at ELSE applied_at END) OVER (PARTITION BY id ORDER BY rank ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) [min_applied_at_add_84]
FROM dbo.Onboarded
) onb

Результаты:

id  rank    onboarded_at    applied_at  lapsed_now  lapsed_ever lapsed_date
A   1       2018-01-01      2018-01-02  1           1           2018-05-27
A   2       2018-01-01      2018-02-03  1           1           2018-05-27
A   3       2018-01-01      2018-03-04  1           1           2018-05-27
B   1       2018-02-01      (null)      0           1           2018-04-26
B   2       2018-02-01      2018-08-01  0           1           2018-04-26
C   1       2018-03-01      2018-04-01  0           1           2018-06-24
C   2       2018-03-01      2018-08-01  0           1           2018-06-24
C   3       2018-03-01      2018-09-01  0           1           2018-06-24

Ключ гарантирует, что ваша оконная функция обращает внимание на все строки в каждом окне, где находятся строкиВХОДИТ НЕОГРАНИЧЕННОЕ ПРЕЦЕДИРОВАНИЕ И НЕОГРАНИЧЕННОЕ СЛЕДУЮЩЕЕ.

Подробнее об их использовании вы можете прочитать здесь .

...