Oracle Database中如何基于另一查询结果执行二次查询?
Oracle基于子查询结果做二次查询的实现方案
针对需要筛选「有存款账户或贷款记录的客户完整信息」的需求,以下是3种在Oracle中可直接运行的实现方式,按适用场景排序:
1. 最直观:IN子查询实现
直接将已写好的UNION查询作为IN的匹配集合,逻辑和需求完全对齐,可读性最高,适合小数据量场景使用:
SELECT c.customer_name, c.customer_street, c.customer_city FROM customer c WHERE c.customer_name IN ( SELECT customer_name FROM depositor UNION SELECT customer_name FROM borrower );
说明:查询里的
UNION本身会自动对两个结果集去重,不需要额外加DISTINCT,不会因为子查询返回重复值导致结果异常。
2. 性能最优:EXISTS半连接实现
如果表数据量较大(十万级以上),优先选EXISTS写法,Oracle优化器对EXISTS半连接的优化更成熟,不需要做两个表全量结果的合并去重,执行效率更高,逻辑和上面的写法完全等价:
SELECT c.* FROM customer c WHERE EXISTS (SELECT 1 FROM depositor d WHERE d.customer_name = c.customer_name) OR EXISTS (SELECT 1 FROM borrower b WHERE b.customer_name = c.customer_name);
说明:EXISTS是判断「存在匹配记录即返回」,只要客户在存款人表有记录、或者在借款人表有记录,就会命中筛选条件,不会产生重复结果。
3. 可选实现:JOIN关联实现
也可以通过左连接的方式实现,但需要额外加去重逻辑,性能通常不如前两种,仅做参考:
SELECT DISTINCT c.* FROM customer c LEFT JOIN depositor d ON c.customer_name = d.customer_name LEFT JOIN borrower b ON c.customer_name = b.customer_name WHERE d.customer_name IS NOT NULL OR b.customer_name IS NOT NULL;
选型建议
- 临时查数、追求写法简单好懂,选IN子查询版本
- 生产环境、表数据量大,选EXISTS半连接版本
- 非必要不选JOIN加DISTINCT的写法,额外的去重操作会带来不必要的性能开销
因为customer表主键是customer_name,以上三种写法最终返回的客户记录都是唯一的,不会出现重复的客户信息行。
内容的提问来源于stack exchange,提问作者Primer Cielo
相关产品推荐
相关产品推荐

