您可以使用分析函数来执行此操作,其优点是只需访问每个表一次。
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
语句 - 有两个但它们是相同的,除了从哪个列返回TABLEB
。本案共有三个条款:
when b.login_id is null then null
如果 中没有匹配的记录TABLEB
,因为外连接B.LOGIN_ID
会为空;这符合您的第三个标准。
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
记录的状态为空,那将是首先看到的。因此,这符合您的第一个条件,并TABLEB.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'
与上一个子句相同,但这次如果第一个值是Y
则不能有任何空值,因为nulls first
再次。(这是假设状态只能是null
或“Y”,这是您的问题所暗示的 - 如果有任何其他状态,那么您的标准中没有指定行为)。因此,如果中的所有匹配行都TABLEB
具有 status Y
,这将使用与您的第二个条件匹配的固定日期值。
请注意,我在这里使用了日期文字;如果您愿意,您可以使用to_date('12/31/2050', 'MM/DD/YYYY')
,但不要使用隐式转换并假设特定的日期掩码将起作用。