美利通,
这种方法使用嵌套的内联视图。我已经在大型数据集上证明了这种方法,它表现得非常好。
理解查询的最佳方式是从最里面的“M”内联视图开始。为了调试和清晰起见,我添加了计数。这标识了每个建筑物的最大(即最近的???)地址 ID:
select maxa.b_id, max(maxa.a_id) a_id, count(*) c
from address maxa
group by maxa.b_id;
下一个“A”内联视图使用上面的“M”内联视图来决定要获取哪个地址,然后加入该地址 id 以返回一组地址字段:
select ma.b_id, ma.a_id, ma.addr1, ma.addr2, ma.addr3, m.c
from address ma,
( select maxa.b_id, max(maxa.a_id) a_id, count(*) c
from address maxa
group by maxa.b_id ) m
where ma.a_id = m.a_id;
上面的“A”内联视图将一组转换后的地址传递给最终查询。BUILDING 和 ADDRESS 之间的关系是 1 到 0..n,而 BUILDING 和“A”之间的关系是 1 到 0..1,这是一个基本的外连接:
select b.b_id, b.b_code, b.b_name, a.*
from building b,
( select ma.b_id, ma.a_id, ma.addr1, ma.addr2, ma.addr3, m.c
from address ma,
( select maxa.b_id, max(maxa.a_id) a_id, count(*) c
from address maxa
group by maxa.b_id ) m
where ma.a_id = m.a_id ) a
where b.b_id = a.b_id (+);
这种方法的主要优点是:
- 提供任意数量的地址列。
- 确定性,每次运行时返回完全相同的结果。
- 不会对您的最终查询造成过度的复杂性,这肯定会比这个更复杂。
- “A” 内联视图可以很容易地封装在数据库视图中,也许称它为 LATEST_ADDRESS 视图:
create view latest_address (b_id, a_id, addr1, addr2, addr3, c) as
select ma.b_id, ma.a_id, ma.addr1, ma.addr2, ma.addr3, m.c
from address ma,
( select maxa.b_id, max(maxa.a_id) a_id, count(*) c
from address maxa
group by maxa.b_id ) m
where ma.a_id = m.a_id;
select b.b_id, b.b_code, b.b_name, a.*
from building b, latest_address a
where b.b_id = a.b_id (+);
享受!
马修