You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动