模仿不存在的行
Imitate rows that don't exist
我需要用默认数据替换不存在的一行。下面是我所拥有的数据,然后是我需要 return 的数据。我想在 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
使用 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 月的 6 个虚拟行。 (我们知道我们不需要 3 月或 9 月的虚拟行)。
然后您可以排除任何具有与 not exists
相同日期的真实数据的数据;并将其与来自真实 table:
的数据合并
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
有了固定的开始日期,您可以修改生成的 table:
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;
您也可以从生成的 table 数据进行左外连接,但当然必须使用旧的 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;
我需要用默认数据替换不存在的一行。下面是我所拥有的数据,然后是我需要 return 的数据。我想在 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
使用 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 月的 6 个虚拟行。 (我们知道我们不需要 3 月或 9 月的虚拟行)。
然后您可以排除任何具有与 not exists
相同日期的真实数据的数据;并将其与来自真实 table:
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
有了固定的开始日期,您可以修改生成的 table:
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;
您也可以从生成的 table 数据进行左外连接,但当然必须使用旧的 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;