【问题标题】:ORACLE SQL: Fill in missing datesORACLE SQL:填写缺失的日期
【发布时间】:2015-04-14 17:53:10
【问题描述】:

我有以下代码,它提供了三十天的生产日期和生产量。

select 
(case when trunc(so.revised_due_date) <= trunc(sysdate) 
    then trunc(sysdate) else trunc(so.revised_due_date) end) due_date, 
(case 
    when (case when sp.pr_typ in ('VV','VD') then 'DVD' when sp.pr_typ in ('RD','CD') 
    then 'CD' end) = 'CD' 
    and  (case when so.tec_criteria in ('PI','MC') 
    then 'XX' else so.tec_criteria end) = 'OF'
    then sum(so.revised_qty_due)
end) CD_OF_VOLUME
from shop_order so
left join scm_prodtyp sp
on so.prodtyp = sp.prodtyp
where so.order_type = 'MD' 
and so.plant = 'W' 
and so.status_code between '4' and '8' 
and trunc(so.revised_due_date) <= trunc(sysdate)+30
group by trunc(so.revised_due_date), so.tec_criteria, sp.pr_typ
order by trunc(so.revised_due_date)

我遇到的问题是没有计划生产的日期,该日期不会出现在报告中。有没有办法补缺日期。

即当前报告显示以下内容...

DUE_DATE    CD_OF_VOLUME 
14/04/2015     35,267.00 
15/04/2015     71,744.00 
16/04/2015     20,268.00 
17/04/2015     35,156.00 
18/04/2015     74,395.00 
19/04/2015      3,636.00 
21/04/2015      5,522.00
22/04/2015     15,502.00
04/05/2015     10,082.00

注意:缺少日期(20/04/2015、23/04/2015 至 03/05/2015)

范围始终是从 sysdate 开始的 30 天。 如何填写缺失的日期? 您需要某种日历表吗?

谢谢

【问题讨论】:

标签: sql oracle


【解决方案1】:

您可以从SYSDATE 获得 30 天的期限,如下所示(我假设您要包括 SYSDATE?):

WITH mydates AS (
    SELECT TRUNC(SYSDATE) - 1 + LEVEL AS due_date FROM dual
   CONNECT BY LEVEL <= 31
)

然后使用上述方法对您的查询执行LEFT JOIN(将您的查询也放在 CTE 中也许不是一个坏主意):

WITH mydates AS (
    SELECT TRUNC(SYSDATE) - 1 + LEVEL AS due_date FROM dual
   CONNECT BY LEVEL <= 31
), myorders AS (
    select 
    (case when trunc(so.revised_due_date) <= trunc(sysdate) 
        then trunc(sysdate) else trunc(so.revised_due_date) end) due_date, 
    (case 
        when (case when sp.pr_typ in ('VV','VD') then 'DVD' when sp.pr_typ in ('RD','CD') 
        then 'CD' end) = 'CD' 
        and  (case when so.tec_criteria in ('PI','MC') 
        then 'XX' else so.tec_criteria end) = 'OF'
        then sum(so.revised_qty_due)
    end) CD_OF_VOLUME
    from shop_order so
    left join scm_prodtyp sp
    on so.prodtyp = sp.prodtyp
    where so.order_type = 'MD' 
    and so.plant = 'W' 
    and so.status_code between '4' and '8' 
    and trunc(so.revised_due_date) <= trunc(sysdate)+30
    group by trunc(so.revised_due_date), so.tec_criteria, sp.pr_typ
    order by trunc(so.revised_due_date)
)
SELECT mydates.due_date, myorders.cd_of_volume
  FROM mydates LEFT JOIN myorders
    ON mydates.due_date = myorders.due_date;

如果您想在“缺失”日期上显示零而不是 NULL,请使用上面的 COALESCE(myorders.cd_of_volume, 0) AS cd_of_volume

【讨论】:

    【解决方案2】:

    您可以这样做: 用你需要的所有日子创建一个新表。

    WITH DAYS AS
    (SELECT TRUNC(SYSDATE) - ROWNUM DDD
     FROM ALL_OBJECTS
     WHERE ROWNUM < 365)
    SELECT
      DAYS.DDD
    FROM
    
      DAYS;
    

    然后在两个表之间进行完全外连接:

    select  DUE_DATE ,   CD_OF_VOLUME , DDD
    from (
        select 
        (case when trunc(so.revised_due_date) <= trunc(sysdate) 
            then trunc(sysdate) else trunc(so.revised_due_date) end) due_date, 
        (case 
            when (case when sp.pr_typ in ('VV','VD') then 'DVD' when sp.pr_typ in ('RD','CD') 
            then 'CD' end) = 'CD' 
            and  (case when so.tec_criteria in ('PI','MC') 
            then 'XX' else so.tec_criteria end) = 'OF'
            then sum(so.revised_qty_due)
        end) CD_OF_VOLUME
        from shop_order so
        left join scm_prodtyp sp
        on so.prodtyp = sp.prodtyp
        where so.order_type = 'MD' 
        and so.plant = 'W' 
        and so.status_code between '4' and '8' 
        and trunc(so.revised_due_date) <= trunc(sysdate)+30
        group by trunc(so.revised_due_date), so.tec_criteria, sp.pr_typ
        order by trunc(so.revised_due_date)
    )  full outer join   NEW_TABLE new on (    new .DDD =  DUE_DATE     )
      where new .DDD between   /* */   AND   /* */   /*   pick your own limit) */
    

    【讨论】:

      【解决方案3】:

      您可以使用connect byleft join 获得gaps

      假设您的 架构 是:

      create table tbl(DUE_DATE date, CD_OF_VOLUME float);
      insert into tbl values(to_date('14/04/2015','DD/MM/YYYY'),35267.00);
      insert into tbl values(to_date('15/04/2015','DD/MM/YYYY'),71744.00); 
      insert into tbl values(to_date('16/04/2015','DD/MM/YYYY'),20268.00); 
      insert into tbl values(to_date('17/04/2015','DD/MM/YYYY'),35156.00); 
      insert into tbl values(to_date('18/04/2015','DD/MM/YYYY'),74395.00); 
      insert into tbl values(to_date('19/04/2015','DD/MM/YYYY'),3636.00); 
      insert into tbl values(to_date('21/04/2015','DD/MM/YYYY'),5522.00);
      insert into tbl values(to_date('22/04/2015','DD/MM/YYYY'),15502.00);
      insert into tbl values(to_date('04/05/2015','DD/MM/YYYY'),10082.00);
      

      你可以说:

      with cte as
      (
        select (select min(DUE_DATE)-1 from tbl)+ level as dt
        from dual
        connect by level <= (select max(DUE_DATE)-min(DUE_DATE) from tbl)
      )
      select to_char(c.dt,'DD/MM/YYYY') gap,null volume 
      from cte c
      left join tbl t on c.dt=t.DUE_DATE
      where t.DUE_DATE is null
      order by c.dt
      

      结果:

      GAP         VOLUME
      20/04/2015  (null)
      23/04/2015  (null)
      24/04/2015  (null)
      25/04/2015  (null)
      26/04/2015  (null)
      27/04/2015  (null)
      28/04/2015  (null)
      29/04/2015  (null)
      30/04/2015  (null)
      01/05/2015  (null)
      02/05/2015  (null)
      03/05/2015  (null)
      

      注意:您可以在原始查询中实现这一点,一种最简单的方法是包装您的查询并将其用作子查询,而不是上面代码中的 tbl - p.

      【讨论】:

        猜你喜欢
        • 2018-06-24
        • 2020-01-31
        • 2018-10-05
        • 2019-06-26
        • 1970-01-01
        • 2020-11-10
        • 1970-01-01
        • 2018-07-15
        相关资源
        最近更新 更多