を有する第二の場合、私はテーブルを作成すべての "必要な日付"とすべての値が0です。次に、参加する代わりにunion all
グループをid
とref_date
でグループ化し、各グループの値を追加します。日付に元のテーブルの値を持つ行がある場合は、結果の値です。そうでない場合、値は0になります。これにより、結合は回避されます。ほとんどすべての場合、union all
+集約は、結合より高速です(場合によってははるかに高速です)。
さらに詳しいテストのために入力データを追加しました。あなたの元の質問では、あなたは2つのidを持っていて、両方とも4つの正の値を持っています。それぞれの場合に5つの値がないため、5つのゼロ(0)があり、どちらの場合も中央値が0であることを意味します。私が追加したid=3
については、3つの正の値と3つのゼロがあります。中央値は最小の正の数の半分です。 id=4
については、私はちょうど1つの値を持っています、そして、中央値でなければなりません。
解決策には、具体的な質問への答え、一時テーブルを作成する方法(一時テーブルではなく、インラインビュー)が含まれます。ファクト・サブクエリ(WITH句内)を使用すると、オプティマイザは、それらを一時表またはインライン・ビューとして扱うかどうかを決定します。 Explain Planを見てオプティマイザが何を決定したかを見ることができます。
with
inputs (id, ref_date, value) as (
select 1, to_date('01/01/2014', 'dd/mm/yyyy'), 20 from dual union all
select 1, to_date('01/02/2014', 'dd/mm/yyyy'), 25 from dual union all
select 1, to_date('01/06/2014', 'dd/mm/yyyy'), 3 from dual union all
select 1, to_date('01/09/2014', 'dd/mm/yyyy'), 6 from dual union all
select 2, to_date('01/04/2015', 'dd/mm/yyyy'), 7 from dual union all
select 2, to_date('01/08/2015', 'dd/mm/yyyy'), 43 from dual union all
select 2, to_date('01/09/2015', 'dd/mm/yyyy'), 85 from dual union all
select 2, to_date('01/12/2015', 'dd/mm/yyyy'), 4 from dual union all
select 3, to_date('01/01/2016', 'dd/mm/yyyy'), 12 from dual union all
select 3, to_date('01/03/2016', 'dd/mm/yyyy'), 23 from dual union all
select 3, to_date('01/06/2016', 'dd/mm/yyyy'), 2 from dual union all
select 4, to_date('01/11/2014', 'dd/mm/yyyy'), 9 from dual
),
-- the "inputs" table constructed above is for testing only,
-- it is not part of the solution.
ranges (id, min_date, max_date) as (
select id, min(ref_date), max(ref_date)
from inputs
group by id
),
prep (id, ref_date, value) as (
select id, add_months(min_date, level - 1), 0
from ranges
connect by level <= 1 + months_between(max_date, min_date)
and prior id = id
and prior sys_guid() is not null
),
v (id, ref_date, value) as (
select id, ref_date, sum(value)
from (select id, ref_date, value from prep union all
select id, ref_date, value from inputs
)
group by id, ref_date
)
select id, median(value) as median_value
from v
group by id
order by id -- ORDER BY is optional
;
ID MEDIAN_VALUE
-- ------------
1 0
2 0
3 1
4 9
あなたは[カレンダーテーブル](http://stackoverflow.com/questions/11576879/calendar-table-in-sql)が必要 – JohnHC
は '日付をref_date'ていますか?そうであれば、フォーマットはありません。それとも特定の形式の 'varchar2'ですか? –