SQL查询优化需求:优化业务员订单列表查询逻辑以提升性能
优化业务员订单列表查询方案
你的实现确实存在N+1查询问题——先查一次去重的订单列表,再循环每个订单号单独查客户信息,订单多的时候不仅代码冗余,性能也会直线下降。咱们直接用一次多表关联查询就能搞定,既简洁又高效。
优化后的SQL查询
直接通过LEFT JOIN关联两张表,用DISTINCT去重(因为同一订单对应多个产品,会产生重复的订单编号/日期/客户名组合),一次就能拿到所有需要的数据:
SELECT DISTINCT O.order_number, O.order_date, C.customer_name FROM orders O LEFT JOIN customers C ON O.customer_id = C.customer_id WHERE O.commercial_id = :commercial_id ORDER BY O.order_date DESC
也可以用GROUP BY替代DISTINCT,效果一致(取决于数据库优化器的选择):
SELECT O.order_number, O.order_date, C.customer_name FROM orders O LEFT JOIN customers C ON O.customer_id = C.customer_id WHERE O.commercial_id = :commercial_id GROUP BY O.order_number, O.order_date, C.customer_name ORDER BY O.order_date DESC
对应的PHP代码实现
现在不需要循环多次查询了,一次执行就能获取所有结果,代码简洁很多:
// 一次查询获取所有符合条件的业务员订单 $req = $bdd->prepare(" SELECT DISTINCT O.order_number, O.order_date, C.customer_name FROM orders O LEFT JOIN customers C ON O.customer_id = C.customer_id WHERE O.commercial_id = :commercial_id ORDER BY O.order_date DESC "); $req->bindParam(':commercial_id', $commercial_id); $req->execute(); $orders = $req->fetchAll(PDO::FETCH_ASSOC); // 如果需要和原来的结果结构一致(用order_number作为数组键),只需简单处理 $ordersIndexed = []; foreach ($orders as $order) { $ordersIndexed[$order['order_number']] = $order; }
优化点说明
- 减少查询次数:从原来的
1+N次查询(N为订单数量)变成1次,大幅降低数据库连接和查询开销 - 逻辑更简洁:去掉了冗余的循环查询逻辑,代码可读性更高
- 利用数据库能力:数据库的关联查询和去重操作比PHP端循环处理效率高得多
额外性能建议
为了让查询更快,可以给orders表添加索引:
- 给
commercial_id字段加索引,加速业务员订单的筛选 - 给
order_number字段加索引,加速去重/分组操作
(customers表的customer_id应该已经是主键索引了,这是关联查询的基础)
内容的提问来源于stack exchange,提问作者Beko




