强制链外连接
Outer join with mandatory chain
假设我有这个数据
人->地址变更->地址变更原因
我想要所有人的详细信息
我还想知道他们是否因为火灾而更改过地址。所以我不想知道原因是什么,但如果他们出于 1 个单一原因更改了地址。
每个人可能有多个地址更改原因
所以我有
SELECT people.*
CASE WHEN add_change.reason_id is not NULL THEN
'Y'
ELSE
'N'
END as been_fire
from people
left outer join add_change ON person.id = add_change.person
left outer join add_change_reason ON add_change.reason_id = add_change_reason.id AND add_change_reason.text = 'FIRE'
但是如果他们有很多地址更改,这 returns 每人多行。
我不能只使用
left outer join add_change ON add_change.person = person.id AND add_change.reason_id = 5
因为这不是固定数据。
使用exists
:
SELECT p.*,
(CASE WHEN EXISTS (SELECT 1
FROM add_change ac JOIN
add_change_reason acr
ON ac.reason_id = acr.id
NVL(address_change.reason,'N')
WHERE p.id = ac.person AND
acr.text = 'FIRE'
)
THEN 'Y' ELSE 'N'
END) as has_fire_address_change
from people p;
请注意,这会将标志更改为 'Y'
和 'N'
,这正是您的问题描述所暗示的。
您可以对派生的 table 进行左连接,只有 returns 个具有更改原因的人员 ID 'FIRE':
SELECT p.*
CASE WHEN cr.person IS NOT NULL THEN 'Y' ELSE 'N' END as been_fire
from people
left join (
select ac.person
from add_change ac
where exists (select *
from add_change_reason acr
where acr.id = ac.reason_id
AND acr.text = 'FIRE')
) cr on cr.person = p.id
假设我有这个数据
人->地址变更->地址变更原因
我想要所有人的详细信息 我还想知道他们是否因为火灾而更改过地址。所以我不想知道原因是什么,但如果他们出于 1 个单一原因更改了地址。
每个人可能有多个地址更改原因
所以我有
SELECT people.*
CASE WHEN add_change.reason_id is not NULL THEN
'Y'
ELSE
'N'
END as been_fire
from people
left outer join add_change ON person.id = add_change.person
left outer join add_change_reason ON add_change.reason_id = add_change_reason.id AND add_change_reason.text = 'FIRE'
但是如果他们有很多地址更改,这 returns 每人多行。
我不能只使用
left outer join add_change ON add_change.person = person.id AND add_change.reason_id = 5
因为这不是固定数据。
使用exists
:
SELECT p.*,
(CASE WHEN EXISTS (SELECT 1
FROM add_change ac JOIN
add_change_reason acr
ON ac.reason_id = acr.id
NVL(address_change.reason,'N')
WHERE p.id = ac.person AND
acr.text = 'FIRE'
)
THEN 'Y' ELSE 'N'
END) as has_fire_address_change
from people p;
请注意,这会将标志更改为 'Y'
和 'N'
,这正是您的问题描述所暗示的。
您可以对派生的 table 进行左连接,只有 returns 个具有更改原因的人员 ID 'FIRE':
SELECT p.*
CASE WHEN cr.person IS NOT NULL THEN 'Y' ELSE 'N' END as been_fire
from people
left join (
select ac.person
from add_change ac
where exists (select *
from add_change_reason acr
where acr.id = ac.reason_id
AND acr.text = 'FIRE')
) cr on cr.person = p.id