Присоединиться и заполнить значения NULL последним ненулевым

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

ID | stmt_dt             ID | renewal_dt
   --                       --
1 |1/31/15                1 | 2/28/15
1 |2/28/15                1 | 4/30/15
1 |3/31/15                2 | 2/28/15
1 |4/30/15                3 | 1/31/15
1 |5/31/15                
2 |1/31/15
2 |2/28/15
2 |3/31/15
2 |4/30/15
2 |5/31/15
3 |1/31/15
3 |2/28/15
3 |3/31/15
3 |4/30/15
3 |5/31/15
4 |1/31/15
4 |2/28/15
4 |3/31/15
4 |4/30/15
4 |5/31/15

Вот мой желаемый вывод

ID | stmt_dt | renewal_dt
   --         
1 |1/31/15   | NA
1 |2/28/15   | 2/28/15          
1 |3/31/15   | 2/28/15         
1 |4/30/15   | 4/30/15          
1 |5/31/15   |  4/30/15           
2 |1/31/15   |  NA
2 |2/28/15   |  2/28/15
2 |3/31/15   |  2/28/15
2 |4/30/15   |  2/28/15
2 |5/31/15   |  2/28/15
3 |1/31/15   |  1/31/15
3 |2/28/15   |  1/31/15
3 |3/31/15   | 1/31/15
3 |4/30/15   |  1/31/15
3 |5/31/15   |  1/31/15
4 |1/31/15   |  NA
4 |2/28/15   |  NA
4 |3/31/15   |  NA
4 |4/30/15   |  NA
4 |5/31/15   |  NA

Моя самая большая проблема заключалась в том, чтобы получить объединенные значения для заполнения до следующего ненулевого значения в каждой группе. Любые идеи о том, как добиться этого присоединения? Спасибо!

3 ответа

ВЫБЕРИТЕ коррелированный запрос

select      s.ID
           ,s.stmt_dt

           ,(   
                select      max (r.renewal_dt)
                from        renewal r
                where       r.ID = s.ID
                        and r.renewal_dt <= s.stmt_dt   
            )   as renewal_dt

from        stmt    s

order by    ID
           ,stmt_dt

+----+------------+------------+
| ID |  stmt_dt   | renewal_dt |
+----+------------+------------+
|  1 | 2015-01-31 |            |
|  1 | 2015-02-28 | 2015-02-28 |
|  1 | 2015-03-31 | 2015-02-28 |
|  1 | 2015-04-30 | 2015-04-30 |
|  1 | 2015-05-31 | 2015-04-30 |
|  2 | 2015-01-31 |            |
|  2 | 2015-02-28 | 2015-02-28 |
|  2 | 2015-03-31 | 2015-02-28 |
|  2 | 2015-04-30 | 2015-02-28 |
|  2 | 2015-05-31 | 2015-02-28 |
|  3 | 2015-01-31 | 2015-01-31 |
|  3 | 2015-02-28 | 2015-01-31 |
|  3 | 2015-03-31 | 2015-01-31 |
|  3 | 2015-04-30 | 2015-01-31 |
|  3 | 2015-05-31 | 2015-01-31 |
|  4 | 2015-01-31 |            |
|  4 | 2015-02-28 |            |
|  4 | 2015-03-31 |            |
|  4 | 2015-04-30 |            |
|  4 | 2015-05-31 |            |
+----+------------+------------+

объединить все + last_value

select      ID
           ,dt  as stmt_dt

           ,last_value (case when tab = 'R' then dt end ignore nulls) over
            (
                partition by    id
                order by        dt  
                               ,case tab when 'R' then 1 else 2 end
            )   as renewal_dt

from        (           select 'S',ID,stmt_dt    from stmt
            union all   select 'R',ID,renewal_dt from renewal
            ) as t (tab,ID,dt)


qualify     tab = 'S'

order by    ID
           ,stmt_dt

+----+------------+------------+
| ID |  stmt_dt   | renewal_dt |
+----+------------+------------+
|  1 | 2015-01-31 |            |
|  1 | 2015-02-28 | 2015-02-28 |
|  1 | 2015-03-31 | 2015-02-28 |
|  1 | 2015-04-30 | 2015-04-30 |
|  1 | 2015-05-31 | 2015-04-30 |
|  2 | 2015-01-31 |            |
|  2 | 2015-02-28 | 2015-02-28 |
|  2 | 2015-03-31 | 2015-02-28 |
|  2 | 2015-04-30 | 2015-02-28 |
|  2 | 2015-05-31 | 2015-02-28 |
|  3 | 2015-01-31 | 2015-01-31 |
|  3 | 2015-02-28 | 2015-01-31 |
|  3 | 2015-03-31 | 2015-01-31 |
|  3 | 2015-04-30 | 2015-01-31 |
|  3 | 2015-05-31 | 2015-01-31 |
|  4 | 2015-01-31 |            |
|  4 | 2015-02-28 |            |
|  4 | 2015-03-31 |            |
|  4 | 2015-04-30 |            |
|  4 | 2015-05-31 |            |
+----+------------+------------+

мин (...) более (... строк от 1 до 1 после 1)* + объединение
* = ВЕДУЩИЙ

select  s.ID
       ,s.stmt_dt
       ,r.renewal_dt

from                stmt    s

        left join  (select  ID
                           ,renewal_dt                              

                           ,min (renewal_dt) over
                            (
                                partition by    ID
                                order by        renewal_dt
                                rows            between 1 following 
                                                and     1 following
                            ) as next_renewal_dt

                    from    renewal
                    ) r

        on          s.ID        =   r.ID

                and s.stmt_dt   >=  r.renewal_dt
                and s.stmt_dt   <   coalesce (r.next_renewal_dt,date '9999-01-01')

order by    s.ID
           ,s.stmt_dt

+----+------------+------------+
| ID |  stmt_dt   | renewal_dt |
+----+------------+------------+
|  1 | 2015-01-31 |            |
|  1 | 2015-02-28 | 2015-02-28 |
|  1 | 2015-03-31 | 2015-02-28 |
|  1 | 2015-04-30 | 2015-04-30 |
|  1 | 2015-05-31 | 2015-04-30 |
|  2 | 2015-01-31 |            |
|  2 | 2015-02-28 | 2015-02-28 |
|  2 | 2015-03-31 | 2015-02-28 |
|  2 | 2015-04-30 | 2015-02-28 |
|  2 | 2015-05-31 | 2015-02-28 |
|  3 | 2015-01-31 | 2015-01-31 |
|  3 | 2015-02-28 | 2015-01-31 |
|  3 | 2015-03-31 | 2015-01-31 |
|  3 | 2015-04-30 | 2015-01-31 |
|  3 | 2015-05-31 | 2015-01-31 |
|  4 | 2015-01-31 |            |
|  4 | 2015-02-28 |            |
|  4 | 2015-03-31 |            |
|  4 | 2015-04-30 |            |
|  4 | 2015-05-31 |            |
+----+------------+------------+
Другие вопросы по тегам