0

存在しない 1 つの行をデフォルト データで置き換える必要があります。以下は、データ用に持っているものと、データ用に返す必要があるものです。PL/SQL で何かを構築するのではなく、SQL でこれを行いたいと考えています。私はオラクル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
4

1 に答える 1

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 月までの 6 つのダミー行が得られます。(3 月または 9 月のダミー行は必要ありません)。

次に、同じ日付の実際のデータを持つものを除外できます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;
于 2016-09-28T17:37:22.673 に答える