Я создаю отчет в Таблице для нового продукта, который фиксирует такие метрики, как ожидающие предыдущие приложения, ожидающие окончания новых приложений и т. Д. Для этого мне нужен снимок состояния конца дня для каждого приложения каждый день. Было принято решение, превышающее мой уровень оплаты, чтобы получить скользящую семидневную дельту данных. Итак, происходит то, что приложение, которое не имело изменения статуса в предыдущие семь дней, перестает появляться в БД, пока не произойдет что-то новое, которое учитывает пробелы в датах и сбрасывает мои цифры в моем отчете. Мне нужен снимок каждого дня для каждого приложения, поэтому при наличии разрыва в датах я хочу взять самую последнюю запись за предыдущий день и вставить ее, чтобы заполнить промежутки между двумя датами. Кроме того, я присоединяюсь к таблице кредитных баллов, и мы иногда извлекаем все три бюро, иногда два, иногда одно, так что на одно приложение может приходиться до трех строк в день.

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

drop table if exists #date
drop table if exists #test

create table #date
    (
        calendar_date date
    )

insert into #date
values
('2019-08-07'),
('2019-08-08'),
('2019-08-09'),
('2019-08-10'),
('2019-08-11'),
('2019-08-12')

create table #test
    (
        id int,
        period_date date,
        decision_status varchar(20),
        credit_score int,
        expired_flag bit
    )

insert into #test (id,period_date,decision_status,credit_score,expired_flag)
values
(1,'2019-08-08','declined',635,null),
(1,'2019-08-08','declined',642,null),
(1,'2019-08-09','declined',635,null),
(1,'2019-08-09','declined',642,null),
(1,'2019-08-10','declined',635,null),
(1,'2019-08-10','declined',642,null),
(1,'2019-08-11','declined',635,null),
(1,'2019-08-11','declined',642,null),
(1,'2019-08-12','declined',635,null),
(1,'2019-08-12','declined',642,null),
(2,'2019-08-08','review',656,null),
(2,'2019-08-08','review',648,null),
(2,'2019-08-09','review',656,null),
(2,'2019-08-09','review',648,null),
(2,'2019-08-12','review',656,null),
(2,'2019-08-12','review',648,null),
(3,'2019-08-08','preapproved',678,null),
(3,'2019-08-08','preapproved',689,null),
(3,'2019-08-08','preapproved',693,null),
(3,'2019-08-09','preapproved',678,null),
(3,'2019-08-09','preapproved',689,null),
(3,'2019-08-09','preapproved',693,null),
(3,'2019-08-11','preapproved',678,1),
(3,'2019-08-11','preapproved',689,1),
(3,'2019-08-11','preapproved',693,1),
(3,'2019-08-12','preapproved',678,1),
(3,'2019-08-12','preapproved',689,1),
(3,'2019-08-12','preapproved',693,1),
(4,'2019-08-08','onboarded',725,null),
(4,'2019-08-09','onboarded',725,null),
(4,'2019-08-10','onboarded',725,null),
(5,'2019-08-08','approved',685,null),
(5,'2019-08-08','approved',675,null),
(5,'2019-08-09','approved',685,null),
(5,'2019-08-09','approved',675,null),
(5,'2019-08-12','approved',685,1),
(5,'2019-08-12','approved',675,1)

И запрос:

select id, calendar_date, period_date, decision_status, credit_score, expired_flag
from #date join
     #test
     on calendar_date=dateadd(day,-1,period_date)
order by id, calendar_date

Мне просто нужно каждое приложение показывать на каждый день.

0
Aaron Cirlin 18 Авг 2019 в 01:11

2 ответа

Лучший ответ

< Сильный > Update : После получения ответа от Гордона, который вдохновил меня и направил меня в правильном направлении, и проведя некоторые дополнительные исследования, я, похоже, нашел решение, которое работает. Я хотел бы поделиться здесь решением на тот случай, если кто-нибудь еще столкнется с этой проблемой. Я публикую код ниже:

drop table if exists #date
drop table if exists #test
drop table if exists #test1
drop table if exists #row_num

create table #date
    (
        calendar_date date
    )

insert into #date
values
('2019-08-07'),
('2019-08-08'),
('2019-08-09'),
('2019-08-10'),
('2019-08-11')

create table #test
    (
        id int,
        period_date date,
        decision_status varchar(20),
        credit_score int,
        expired_flag bit
    )

insert into #test (id,period_date,decision_status,credit_score,expired_flag)
values
(1,'2019-08-08','declined',635,null),
(1,'2019-08-08','declined',642,null),
(1,'2019-08-09','declined',635,null),
(1,'2019-08-09','declined',642,null),
(1,'2019-08-10','declined',635,null),
(1,'2019-08-10','declined',642,null),
(1,'2019-08-11','declined',635,null),
(1,'2019-08-11','declined',642,null),
(1,'2019-08-12','declined',635,null),
(1,'2019-08-12','declined',642,null),
(2,'2019-08-08','review',656,null),
(2,'2019-08-08','review',648,null),
(2,'2019-08-09','review',656,null),
(2,'2019-08-09','review',648,null),
(2,'2019-08-12','review',656,null),
(2,'2019-08-12','review',648,null),
(3,'2019-08-08','preapproved',678,null),
(3,'2019-08-08','preapproved',689,null),
(3,'2019-08-08','preapproved',693,null),
(3,'2019-08-09','preapproved',678,null),
(3,'2019-08-09','preapproved',689,null),
(3,'2019-08-09','preapproved',693,null),
(3,'2019-08-11','preapproved',678,1),
(3,'2019-08-11','preapproved',689,1),
(3,'2019-08-11','preapproved',693,1),
(3,'2019-08-12','preapproved',678,1),
(3,'2019-08-12','preapproved',689,1),
(3,'2019-08-12','preapproved',693,1),
(4,'2019-08-08','onboarded',725,null),
(4,'2019-08-09','onboarded',725,null),
(4,'2019-08-10','onboarded',725,null),
(5,'2019-08-08','approved',685,null),
(5,'2019-08-08','approved',675,null),
(5,'2019-08-09','approved',685,null),
(5,'2019-08-09','approved',675,null),
(5,'2019-08-12','approved',685,1),
(5,'2019-08-12','approved',675,1)

select id,calendar_date,decision_status,credit_score,expired_flag
      ,ROW_NUMBER() over(partition by id,calendar_date order by calendar_date) as row_id
      ,cast(ROW_NUMBER() over(partition by id,calendar_date order by calendar_date) as char(1)) as row_num
into #test1
from #date
join #test
    on calendar_date=dateadd(day,-1,period_date)
order by id,calendar_date

create table #row_num
    (
        row_id int,
        row_num char(1)
    )

insert into #row_num
values
(1,'1'),
(2,'2'),
(3,'3')

select i.id 
       ,d.calendar_date
       ,coalesce(t.decision_status,t1.decision_status) as decision_status
       ,coalesce(t.credit_score,t1.credit_score) as credit_score
       ,coalesce(t.expired_flag,t1.expired_flag) as expired_flag
from #date d 
     cross join
     (select distinct id 
      from #test1 ) i
     cross join #row_num r 
     left join #test1 t
        on t.id=i.id
        and t.row_id=r.row_id
        and t.calendar_date=d.calendar_date
     join
     (select id,row_id,decision_status,credit_score,expired_flag
             ,calendar_date as start_date
             ,lead(calendar_date,1,dateadd(day,1,(select max(calendar_date) from #date)))
              over (partition by id,row_id order by calendar_date) as end_date
      from #test1
     ) t1
        on t1.id=i.id
        and t1.row_id=r.row_id
        and d.calendar_date>=t1.start_date
        and d.calendar_date<t1.end_date
order by i.id,d.calendar_date,r.row_id

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

0
Aaron Cirlin 18 Авг 2019 в 20:44

Вам может понадобиться left join: просто нужно left join:

select t.id, d.calendar_date, t.period_date, t.decision_status, t.credit_score, t.expired_flag
from #date d left join
     #test t
     on d.calendar_date = dateadd(day, -1, t.period_date)
order by id, d.calendar_date;

Если под «приложением» вы подразумеваете id в #test, то используйте cross join для генерации строк и outer apply для заполнения значений:

select t.id, d.calendar_date, t.period_date, t.decision_status, t.credit_score, t.expired_flag
from #date d cross join
     (select distinct id from #test) i outer apply
     (select top (1) t.*
      from #test t
      where t.id = i.id and t.date <= d.date
      order by t.date desc
     ) t
0
Gordon Linoff 17 Авг 2019 в 22:13