ここに1つの方法です:
with table1 as (select 1 usr, to_date('01/01/2010', 'dd/mm/yyyy') start_date, to_date('31/03/2010', 'dd/mm/yyyy') end_date, 'abc' parameter from dual union all
select 1 usr, to_date('01/04/2010', 'dd/mm/yyyy') start_date, to_date('30/06/2010', 'dd/mm/yyyy') end_date, 'abc' parameter from dual union all
select 1 usr, to_date('01/01/2010', 'dd/mm/yyyy') start_date, to_date('31/03/2010', 'dd/mm/yyyy') end_date, 'xyz' parameter from dual union all
select 1 usr, to_date('01/04/2010', 'dd/mm/yyyy') start_date, to_date('30/06/2010', 'dd/mm/yyyy') end_date, 'xyz' parameter from dual union all
select 1 usr, to_date('01/01/2010', 'dd/mm/yyyy') start_date, to_date('31/03/2010', 'dd/mm/yyyy') end_date, 'qqq' parameter from dual union all
select 1 usr, to_date('01/04/2010', 'dd/mm/yyyy') start_date, to_date('30/06/2010', 'dd/mm/yyyy') end_date, 'qqq' parameter from dual),
table2 as (select 1 usr, to_date('01/01/2009', 'dd/mm/yyyy') start_date, to_date('31/03/2009', 'dd/mm/yyyy') end_date, 'abc' parameter, 100 value from dual union all
select 1 usr, to_date('01/04/2009', 'dd/mm/yyyy') start_date, to_date('30/06/2009', 'dd/mm/yyyy') end_date, 'abc' parameter, 200 value from dual union all
select 1 usr, to_date('01/01/2009', 'dd/mm/yyyy') start_date, to_date('31/03/2009', 'dd/mm/yyyy') end_date, 'xyz' parameter, 300 value from dual union all
select 1 usr, to_date('01/04/2009', 'dd/mm/yyyy') start_date, to_date('30/06/2009', 'dd/mm/yyyy') end_date, 'xyz' parameter, 400 value from dual union all
select 1 usr, to_date('01/01/2009', 'dd/mm/yyyy') start_date, to_date('31/03/2009', 'dd/mm/yyyy') end_date, 'qqq' parameter, 500 value from dual union all
select 1 usr, to_date('01/04/2009', 'dd/mm/yyyy') start_date, to_date('30/06/2009', 'dd/mm/yyyy') end_date, 'qqq' parameter, 600 value from dual)
-- end of mimicking your tables; see SQL below:
select usr,
start_date,
end_date,
parameter,
latest_value,
diff_days
from (select usr,
start_date,
end_date,
parameter,
last_value(value ignore nulls) over (partition by usr, parameter order by start_date) latest_value,
start_date - last_value(case when value is not null then start_date end ignore nulls) over (partition by usr, parameter order by start_date) diff_days
from (select usr,
start_date,
end_date,
parameter,
cast(null as number) value
from table1
union all
select usr,
start_date,
end_date,
parameter,
value
from table2))
where diff_days > 0;
USR START_DATE END_DATE PARAMETER LATEST_VALUE DIFF_DAYS
---------- ----------- ----------- --------- ------------ ----------
1 01 jan 2010 31 mar 2010 abc 200 275
1 01 apr 2010 30 jun 2010 abc 200 365
1 01 jan 2010 31 mar 2010 qqq 600 275
1 01 apr 2010 30 jun 2010 qqq 600 365
1 01 jan 2010 31 mar 2010 xyz 400 275
1 01 apr 2010 30 jun 2010 xyz 400 365
これは、最新のnull以外の値を見つけるために分析関数last_value()
を使用していますが、値とそれに対応するend_dateを計算し、その後、必要な減算を行って、後の期間と最新の有効期間の開始との間の差を取得する 日付。
N.B.これは、両方のテーブルに期間が重複していないことを前提としています。
このデータは、実際には同じテーブル内のすべてではなく、2つの異なるテーブルにありますか? – Boneist
どうすれば 'nearest'を定義していますか?table1の終わりより前に終了する最新のtable2?あるいは、それが古いものよりも早く始まったならば、将来の記録は許されるでしょう - そしてもし彼らが結ばれたらどうなりますか? –
@Boneist - 彼らは別のテーブルにあります – dang