分析関数を使用してこれを行うことができます。これには、各テーブルに 1 回しかヒットしないという利点があります。
select distinct a.login_id,
case when b.login_id is null then null
when first_value(b.status) over (partition by b.login_id
order by b.status nulls first) is null then b.resign_date
when first_value(b.status) over (partition by b.login_id
order by b.status nulls first) = 'Y' then date '2050-12-31'
end as resign_date,
case when b.login_id is null then null
when first_value(b.status) over (partition by b.login_id
order by b.status nulls first) is null then b.last_date
when first_value(b.status) over (partition by b.login_id
order by b.status nulls first) = 'Y' then date '2050-12-31'
end as last_date
from tablea a
left join tableb b on b.login_id = a.login_id
order by a.login_id;
関連する部分はcase
ステートメントです。2 つありますが、どちらの列が から返されるかを除けば同じTABLEB
です。ケースには次の 3 つの条項があります。
when b.login_id is null then null
に一致するレコードがない場合TABLEB
、外部結合B.LOGIN_ID
により null になります。これは 3 番目の条件に一致します。
when first_value(b.status) over (partition by b.login_id
order by b.status nulls first) is null then b.resign_date
このfirst_value()
関数は、「最も低い」ステータス値を返します。nulls first
これは、一致するTABLEB
レコードのいずれかが null ステータスである場合、それが最初に表示されることを意味します。したがって、これは最初の基準に一致しTABLEB.RESIGN_DATE
、その null ステータス行を使用します。
when first_value(b.status) over (partition by b.login_id
order by b.status nulls first) = 'Y' then date '2050-12-31'
前の句と同じですが、今回は最初の値が である場合Y
、再度のために null は存在できませんnulls first
。(これは、ステータスが「Y」または「Y」にしかならないことを前提としています。これはnull
、質問が意味することです。他のステータスがある場合、動作は基準で指定されていません)。したがって、一致するすべての行TABLEB
が statusY
である場合、2 番目の条件に一致する固定の日付値が使用されます。
ここでは日付リテラルを使用していることに注意してください。必要に応じて を使用できますがto_date('12/31/2050', 'MM/DD/YYYY')
、暗黙的な変換を使用せず、特定の日付マスクが使用されると想定してください。