oracle 如果为空,则获取最近的非空值填充

w6mmgewl  于 2023-05-16  发布在  Oracle
关注(0)|答案(3)|浏览(233)

我得到一个只有3个记录的表,如:

Date          Amt
02/04/2023    100
03/04/2023    102
06/04/2023    200

有没有什么方法可以像这样得到非空值填充空值:(从表中我们没有04/04和05/04,然后从03/04获得最接近的值)

Date           Amt
02/04/2023     100
03/04/2023     102
04/04/2023     102
05/04/2023     102
06/04/2023     200

使用Oracle 19 c。

ilmyapht

ilmyapht1#

最简单的解决方案之一:

with t(date_dt,Amt) as (
 select date'2023-04-02', 100 from dual union all
 select date'2023-04-03', 102 from dual union all
 select date'2023-04-06', 200 from dual
)
select 
   missing_dt as dt
  ,amt 
from (
     select date_dt,amt, lead(date_dt)over(order by date_dt) next_dt
     from t
     )
     cross apply (
        select date_dt+level-1 as missing_dt
        from dual
        connect by date_dt+level<=next_dt
     );

DBFiddle:https://dbfiddle.uk/-6zXTodR

sqyvllje

sqyvllje2#

使用递归cte获取缺失的日期。
使用last_value ignore nulls获取最新的当前/前一个(非空)值。

with dates (dat) as (
  select min(dat) from t
  union all
  select dat + interval '1' day from dates
  where dat < (select max(dat) from t)
  )
select d.dat, last_value(t.amt) ignore nulls over (order by d.dat)
from dates d
left join t on d.dat = t.dat
order by d.dat

https://dbfiddle.uk/bkxuhZFX

kzmpq1sx

kzmpq1sx3#

其中一个选项可以是使用分析函数LAST_VALUE()来完成,数据集是用LEVEL ...准备的。通过填写缺失的日期连接:

WITH        -- Sample Data
    tbl (DT, AMNT) AS
        ( Select To_date( '02.04.2023', 'dd.mm.yyyy'), 100 From Dual Union All
            Select To_date( '03.04.2023', 'dd.mm.yyyy'), 102 From Dual Union All
            Select To_date( '06.04.2023', 'dd.mm.yyyy'), 200 From Dual
        )
--    M a i n   S Q L :
SELECT    X_DT "DT", 
          Nvl(AMNT, LAST_VALUE(AMNT IGNORE NULLS) Over(Order By X_DT Rows Between Unbounded Preceding And 1 Preceding)) "AMNT"
FROM  (   Select      DAY_ID, t.DT, t.AMNT, 
                    x.MIN_DT, x.MAX_DT, x.MNTH_ID, 
                    Case  When DAY_ID <= To_Char(LAST_DAY(To_Date('01.' || MNTH_ID, 'dd.mm.yyyy')), 'dd') 
                          Then To_Date(DAY_ID || '.' || MNTH_ID, 'dd.mm.yyyy') 
                    End "X_DT"
          From      (  Select LPAD(LEVEL, 2, '0') "DAY_ID" From Dual Connect By LEVEL <= 31    ) d
          Left Join ( Select To_Char(DT, 'mm.yyyy') "MNTH_ID", Min(DT) "MIN_DT", Max(DT) "MAX_DT" From tbl Group By To_Char(DT, 'mm.yyyy')) x ON(1 = 1) 
          Left Join tbl t ON(t.DT = Case  When DAY_ID <= To_Char(LAST_DAY(To_Date('01.' || MNTH_ID, 'dd.mm.yyyy')), 'dd') 
                                          Then To_Date(DAY_ID || '.' || MNTH_ID, 'dd.mm.yyyy') 
                                    End)
      )
WHERE X_DT Between MIN_DT And MAX_DT
ORDER BY X_DT
--
--  R e s u l t :
DT              AMNT
--------- ----------
02-APR-23        100
03-APR-23        102
04-APR-23        102
05-APR-23        102
06-APR-23        200

相关问题