SQL:单个人存在多个地址。如果存在则选择当前地址,否则选择永久地址
Posted
技术标签:
【中文标题】SQL:单个人存在多个地址。如果存在则选择当前地址,否则选择永久地址【英文标题】:SQL: Multiple addresses present for single person. Select current address if present otherwise select permanent address 【发布时间】:2021-03-16 13:06:26 【问题描述】:我有这种情况,如果有人有当前地址,则需要选择该地址,否则选择永久地址。
我不想将Address
表与Person
加入两次,因为这会影响性能。
人
| person_id | name | surname
+-----------+-------+----------
| 10 | ABC10 | XYZ10
| 11 | ABC11 | XYZ11
| 12 | ABC12 | XYZ12
| 13 | ABC13 | XYZ13
地址
| ID | person_id | type | address | city
+-------+-----------+-----------+-----------+----------
| 1 | 10 | Permanent | addr 10P | city 10P
| 2 | 10 | Current | addr 10C | city 10C
| 3 | 11 | Permanent | addr 11P | city 11P
| 4 | 12 | Permanent | addr 12P | city 12P
| 5 | 12 | Current | addr 12C | city 12C
| 6 | 13 | Permanent | addr 13P | city 13P
预期输出:
| person_id | name | surname | type | address | city
+-----------+-------+-----------+-----------+-----------+-----------
| 10 | ABC10 | XYZ10 | Current | addr 10C | city 10C
| 11 | ABC11 | XYZ11 | Permanent | addr 11P | city 11P
| 12 | ABC12 | XYZ12 | Current | addr 12C | city 12C
| 13 | ABC13 | XYZ13 | Permanent | addr 13P | city 13P
谢谢!
【问题讨论】:
【参考方案1】:一个选项使用横向连接和 fetch 子句:
select p.*, a.type, a.address, a.city
from person p
cross apply (
select a.*
from address a
where a.person_id = p.person_id
order by case a.type when 'Current' then 1 else 2 end
fetch first row only
) a
您还可以使用窗口函数(这适用于所有 Oracle 版本):
select p.*, a.type, a.address, a.city
from person p
inner join (
select a.*,
row_number() over(partition by person_id order by case type when 'Current' then 1 else 2 end) as rn
from address a
) a on a.person_id = p.person_id
where a.rn = 1
case
表达式可以轻松地使用更多可能的地址类型扩展优先级逻辑。如果您只有两个值,“Permanent”和“Current”,那么可以在两个查询中将其简化为:order by type
(这会将“Current”放在首位)。
【讨论】:
【参考方案2】:您可以使用窗口函数来解决这个问题:
select p.*, a.type, a.address, a.city
from person p join
(select a.*,
row_number() over (partition by a.person_id order by a.type) as seqnum
from address a
) a
on a.person_id = p.person_id and a.seqnum = 1;
注意:这里假设类型只有“当前”和“永久”,所以它使用字符串排序来选择“当前”。
【讨论】:
【参考方案3】:您可以根据需要使用row_number
或rank
或dense_rank
函数。
使用row_number
的方法如下:
select * from
(select p.*, a.type, a.address, a.city,
row_number() over (partition by a.person_id order by a.type) as rn
from person p join address a
on a.person_id = p.person_id
) where rn = 1;
【讨论】:
以上是关于SQL:单个人存在多个地址。如果存在则选择当前地址,否则选择永久地址的主要内容,如果未能解决你的问题,请参考以下文章
t-sql 如果记录存在则选择一列,如果不存在则选择不同的列