模仿不存在的行

时间:2016-09-28 17:12:01

标签: sql oracle oracle8i

我需要将默认数据替换为不存在的一行。下面是我所拥有的数据,然后是我需要返回的数据。我希望在SQL中执行此操作,而不是在PL / SQL中构建内容。我正在使用Oracle 8i。

我有什么:

Item     Period_start_date     Qty_Used
1234     1-MAR-2015            10
1234     1-JUN-2015            32
1234     1-JUL-2015            14
1234     1-SEP-2015            11

我需要什么:

1234     1-MAR-2015            10
1234     1-APR-2015            0
1234     1-MAY-2015            0
1234     1-JUN-2015            32
1234     1-JUL-2015            14
1234     1-AUG-2015            0
1234     1-SEP-2015            11

1 个答案:

答案 0 :(得分:3)

使用8i使其比以后的版本更复杂。

您可以使用分层查询生成现有数据所涵盖范围内所有月份的列表,从最早的日期和月数开始:

select item, min(period_start_date) min_date,
  months_between(max(period_start_date), min(period_start_date)) as num_months
from your_table
group by item

...并将其用作分层查询的内部查询:

select item, add_months(min_date, level) as period_start_date
from (
  select item, min(period_start_date) min_date,
    months_between(max(period_start_date), min(period_start_date)) as num_months
  from your_table
  group by item
)
connect by level < num_months

在这种情况下,对于4月到8月,这给了你六个虚拟行。 (我们知道三月或九月我们不需要虚拟行。)

然后,您可以使用not exists排除任何具有相同日期的实际数据的内容;并与真实表中的数据联合起来:

select item, period_start_date, qty_used
from your_table
union all
select item, period_start_date, 0
from (
  select item, add_months(min_date, level) as period_start_date
  from (
    select item, min(period_start_date) min_date,
      months_between(max(period_start_date), min(period_start_date)) as num_months
    from your_table
    group by item
  )
  connect by level < num_months
) t
where not exists (
  select null
  from your_table
  where item = t.item
  and period_start_date = t.period_start_date
)
order by item, period_start_date;

      ITEM PERIOD_STAR   QTY_USED
---------- ----------- ----------
      1234 01-MAR-2015         10
      1234 01-APR-2015          0
      1234 01-MAY-2015          0
      1234 01-JUN-2015         32
      1234 01-JUL-2015         14
      1234 01-AUG-2015          0
      1234 01-SEP-2015         11

使用固定的开始日期,您可以修改生成的表格:

select item, period_start_date, qty_used
from your_table
union all
select item, period_start_date, 0
from (
  select item, add_months(date '2013-03-01', level - 1) as period_start_date
  from (select distinct item from your_table)
  connect by add_months(date '2013-03-01', level - 1) < sysdate
) t
where not exists (
  select null
  from your_table
  where item = t.item
  and period_start_date = t.period_start_date
)
order by item, period_start_date;

您也可以从生成的表数据中保留外连接,但当然必须使用旧的Oracle特定语法:

select t.item, t.period_start_date, nvl(yt.qty_used, 0) as qty
from (
  select item, add_months(date '2013-03-01', level - 1) as period_start_date
  from (select distinct item from your_table)
  connect by add_months(date '2013-03-01', level - 1) < sysdate
) t, your_table yt
where yt.item (+) = t.item
and yt.period_start_date (+) = t.period_start_date
order by t.item, t.period_start_date;