如何改写不含子查询的关联orders与despatch表的SQL查询语句
改写方案:移除WHERE子句中的子查询
当然可以!我们有几种方式能改写这个查询,把原语句WHERE子句里的子查询去掉,让语句结构更清晰或者性能更优。下面给你几个实用的方案:
方案1:使用ROW_NUMBER()窗口函数
这种方法通过窗口函数给agent_code='A004'的订单按日期倒序排名,只保留排名第一的记录(也就是最新日期的订单),再关联despatch表。
SELECT o.*, d.* FROM ( SELECT *, ROW_NUMBER() OVER (ORDER BY ord_date DESC) AS rn FROM orders WHERE agent_code = 'A004' ) o LEFT JOIN despatch d ON o.agent_code = d.agent_code WHERE o.rn = 1;
说明:因为我们只关注A004这一个代理,所以PARTITION BY可以省略,直接按日期倒序排取第一行就行。如果以后要扩展到多个代理的场景,再加PARTITION BY agent_code即可。
方案2:使用JOIN关联最大日期记录
我们可以先单独计算出A004代理的最大订单日期,通过JOIN的方式和原orders表关联,替代原来WHERE里的子查询:
SELECT o.*, d.* FROM orders o LEFT JOIN despatch d ON o.agent_code = d.agent_code JOIN ( SELECT MAX(ord_date) AS max_ord_date FROM orders WHERE agent_code = 'A004' ) max_date ON o.ord_date = max_date.max_ord_date WHERE o.agent_code = 'A004';
说明:这里的JOIN子查询只会计算一次A004的最大日期,逻辑上和原查询完全一致,但把条件从WHERE移到了JOIN里,避免了WHERE子句中嵌套子查询的写法。
方案3:使用MAX()窗口函数过滤
这种方法通过窗口函数直接计算A004代理的最大订单日期,然后在外部过滤出日期等于最大日期的记录:
SELECT * FROM ( SELECT o.*, d.*, MAX(o.ord_date) OVER () AS max_ord_date FROM orders o LEFT JOIN despatch d ON o.agent_code = d.agent_code WHERE o.agent_code = 'A004' ) filtered WHERE ord_date = max_ord_date;
说明:因为已经限定了agent_code='A004',所以MAX() OVER()会直接计算该代理的最大订单日期,后续过滤匹配的记录即可。
这几种方案都能实现和原查询完全一致的效果,你可以根据自己数据库的支持情况(比如窗口函数的兼容性)和实际性能需求来选择。
内容的提问来源于stack exchange,提问作者Mohamed Sahir
相关产品推荐
相关产品推荐

