分析関数を使用してこれを行うことができます。これには、各テーブルに 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')、暗黙的な変換を使用せず、特定の日付マスクが使用されると想定してください。