編集:大幅に改訂。
最初の解決策は、個々のフィールドが異なる時期に変化することから生じる問題を考慮していませんでした。元の effective_date 値に最新の更新を適用することだけに関心がありました。
これはその回答を書き直したものであり、変更されている各フィールドがまとめてではなく個別に考慮されるようにします。
すべての sql は sqlfiddle で示されています: http://sqlfiddle.com/#!4/ca4f4/6
任意の単一フィールドの最新の変更を取得することから始めます。これでそれを達成できます:
select *
from ( select empid, when, what from updates
where when <= to_date('2012-05-10', 'yyyy-mm-dd')
) pivot_data
pivot ( max(when)
for what in ('region' as max_region_date,
'city' as max_city_date,
'country' max_country_date)
);
これにより、ピボット テーブルが作成され、各フィールドが個別に考慮され、レポートの発効日以下の最大日付が出力されます。このピボット テーブルはより大きなクエリに追加されるため、レポートの日付が埋め込まれる場所にすぎないことに注意してください。
元のセットにさらにデータを追加するには、次を使用しましょう。
EMPID NEW WHAT WHEN
1 germany region May, 01 2012
1 germany country May, 01 2012
1 münchen city May, 01 2012
2 boston city June, 01 2012
2 canada country July, 01 2012
2 toronto city July, 01 2012
2 vancouver city August, 01 2012
したがって、8 月 15 日のレポート日付に対して上記のクエリを実行すると、次のようになります。
EMPID MAX_REGION_DATE MAX_CITY_DATE MAX_COUNTRY_DATE
1 May, 01 2012 May, 01 2012 May, 01 2012
2 (null) August, 01 2012 July, 01 2012
(null) は、empid = 2 の領域に更新のエントリがないことを表します。empid = 2 の他の 2 つの日付は、そのフィールドの最新の変更日を表します。
new
次に、これを各フィールドのその日付の値に変換する必要があります。これは、次のような方法で実行できます。
select distinct u1.empid,
(select u2.new from updates u2
where u2.what = 'region'
and u2.empid = u1.empid
and u2.when = max_dates.max_region_date
) region, max_dates.max_region_date,
(select u3.new from updates u3
where u3.what = 'country'
and u3.empid = u1.empid
and u3.when = max_dates.max_country_date
) country, max_dates.max_country_date,
(select u4.new from updates u4
where u4.what = 'city'
and u4.empid = u1.empid
and u4.when = max_dates.max_city_date
) city, max_dates.max_city_date
from updates u1
left join
(select *
from ( select empid, when, what from updates
where when <= to_date('2012-07-15', 'yyyy-mm-dd')
) pivot_data
pivot ( max(when)
for what in ('region' as max_region_date,
'city' as max_city_date,
'country' max_country_date)
)
) max_dates on max_dates.empid = u1.empid;
上記のピボット テーブル出力を派生テーブルとして埋め込み、特定の日付に対応する各フィールド値を個別に選択しています。
これを 15.August のレポートで実行すると、次のようになります。
EMPID REGION MAX_REGION_DATE COUNTRY MAX_COUNTRY_DATE CITY MAX_CITY_DATE
2 (null) (null) canada July, 01 2012 vancouver August, 01 2012
1 germany May, 01 2012 germany May, 01 2012 münchen May, 01 2012
従業員 2 については、国の値が canada であり、7 月 1 日に更新されたのに対し、最新の都市であるバンクーバーはその後の 8 月 1 日に更新されていることがわかります。
ここで、これを従業員に対するクエリと組み合わせる必要があります。
select e.empid, e.name,
(coalesce( u.region, e.region)) region,
(coalesce( u.city, e.city)) city,
(coalesce( u.country, e.country)) country
from employee e
left join (
select distinct u1.empid,
(select u2.new from updates u2
where u2.what = 'region'
and u2.empid = u1.empid
and u2.when = max_dates.max_region_date
) region, max_dates.max_region_date,
(select u3.new from updates u3
where u3.what = 'country'
and u3.empid = u1.empid
and u3.when = max_dates.max_country_date
) country, max_dates.max_country_date,
(select u4.new from updates u4
where u4.what = 'city'
and u4.empid = u1.empid
and u4.when = max_dates.max_city_date
) city, max_dates.max_city_date
from updates u1
left join
(select *
from ( select empid, when, what from updates
where when <= to_date('2012-08-15', 'yyyy-mm-dd')
) pivot_data
pivot ( max(when)
for what in ('region' as max_region_date,
'city' as max_city_date,
'country' max_country_date)
)
) max_dates on max_dates.empid = u1.empid
) u on u.empid = e.empid
order by e.empid;
この最大の部分は、前に示した派生テーブルです。残りは に対して結合しemployee
、次に「null を合体」しing to either take the updated value, or the current value in employee if the update value is
ます。
これにより、次の結果が得られます。
EMPID NAME REGION CITY COUNTRY
1 james germany münchen germany
2 mike americas vancouver canada
8月15日のレポート日付を使用する場合。上記の sqlfiddle で、私のテスト データに対して (または独自のデータを追加して) 他の日付を検証できます。
では、最終課題です。上記は、更新が将来のみであることを検証するためのデータ整合性制約があることを前提としています。更新が従業員テーブルに適用されると (したがって、その effective_date フィールドが更新されます)、その行は更新テーブルから削除されます。つまり、更新は適用されていない変更のみで構成されます。
その場合を考慮したい場合は、フィールドごとに個別に選択して再度チェックする必要があります。上記の選択を次のように変更します。
select e.empid, e.name,
(coalesce( (case
when (u.max_region_date > e.effective_date)
then u.region
end),
e.region)) region,
(coalesce( (case
when (u.max_city_date > e.effective_date)
then u.city
end),
e.city)) city,
(coalesce( (case
when (u.max_country_date > e.effective_date)
then u.country
end),
e.country)) country
from . . . . . the from in the previous query above . . .
私の場合、以前と同じ出力が得られます。
when
追加する必要がありますが、予約語を使用しないこと、およびnew
列名に使用しないことについて、Glenn に同意します。(サンプルに残しましたが。)