记录一次sql查询union的优化

1.原来的sql:

SELECT  t.city_id as cityId,t.city_name as cityName, t.group_id as groupId, t.supplier_name as supplierName,t.id,t.driver_name as driverName,t.license_plates as licensePlates,t.driver_id as driverId,
    t.driver_phone as driverPhone,
    case WHEN m.`status`=1 THEN m.main_order_no  ELSE '' END mainOrder,
    case WHEN m.`status`=1 THEN m.main_name  ELSE '' END subRouteName,
    case WHEN m.`status`=1 THEN m.main_time  ELSE '' END mainOrderTime
    FROM main_order_inter_city m inner JOIN  driver_info_inter_city t
    on t.driver_id =  m.driver_id
    WHERE 1=1   and m.status=1 and t.status =1
        
        UNION
      SELECT t.city_id as cityId,t.city_name as cityName, t.group_id as groupId, t.supplier_name as supplierName,t.id,t.driver_name as driverName,t.license_plates as licensePlates,t.driver_id as driverId,
    t.driver_phone as driverPhone,
    case WHEN m.`status`=1 THEN '' ELSE '' END mainOrder,
    case WHEN m.`status`=1 THEN ''  ELSE '' END subRouteName,
    case WHEN m.`status`=1 THEN ''  ELSE '' END mainOrderTime
    FROM driver_info_inter_city t left JOIN  main_order_inter_city m  
    on t.driver_id =  m.driver_id
    WHERE  1=1  and t.status =1   

    GROUP BY t.driver_id
        

 查询的场景是这样的: 司机表和订单表的数据,需要展示在订单表已经有的司机,如果司机是已经完单,则显示为空闲,然后可以继续给改司机派单子。如果是已经出发,需要显示当前司机是已出发、已到达或者已经完成这样的状态。所以需要显示当前有订单的司机以及空闲的司机。

但是用上面的sql  使用执行计划查看:

 

主要问题出现在下面的union的 left join 。 因为要查询出来空闲的司机,刚开始使用了inner join ,但是发现数据不准确。发现这个慢sql 后,联系到场景是 要展示空闲的司机的,那么这个订单表

其实没必要全表扫描的,只需要查询一条即可。于是改为这样

SELECT  t.city_id as cityId,t.city_name as cityName, t.group_id as groupId, t.supplier_name as supplierName,t.id,t.driver_name as driverName,t.license_plates as licensePlates,t.driver_id as driverId,
    t.driver_phone as driverPhone,
    case WHEN m.`status`=1 THEN m.main_order_no  ELSE '' END mainOrder,
    case WHEN m.`status`=1 THEN m.main_name  ELSE '' END subRouteName,
    case WHEN m.`status`=1 THEN m.main_time  ELSE '' END mainOrderTime
    FROM main_order_inter_city m inner JOIN  driver_info_inter_city t
    on t.driver_id =  m.driver_id
    WHERE 1=1   and m.status=1 and t.status =1
        
        UNION
      SELECT t.city_id as cityId,t.city_name as cityName, t.group_id as groupId, t.supplier_name as supplierName,t.id,t.driver_name as driverName,t.license_plates as licensePlates,t.driver_id as driverId,
    t.driver_phone as driverPhone,
    case WHEN m.`status`=1 THEN '' ELSE '' END mainOrder,
    case WHEN m.`status`=1 THEN ''  ELSE '' END subRouteName,
    case WHEN m.`status`=1 THEN ''  ELSE '' END mainOrderTime
    FROM driver_info_inter_city t left JOIN   (SELECT *  FROM main_order_inter_city WHERE id = 1 ) m  
    on t.driver_id =  m.driver_id
    WHERE  1=1  and t.status =1   

    GROUP BY t.driver_id

查询结果和上面的一样的,sql执行计划

 

问题解决 

原文地址:https://www.cnblogs.com/thinkingandworkinghard/p/12330284.html