【问题标题】:Improve MySQL Union Statement改进 MySQL Union 语句
【发布时间】:2015-03-04 02:40:39
【问题描述】:

我有以下 mySql 语句,我确信它可以提高效率,我只是不确定什么是最好的方法......唯一的区别是在 WHERE 子句中更改的equip_id......

==============

 (SELECT 
        `receipt_ts`, 
        `driver_id`,
        `equip_id`, 
        `pos_lon`, 
        `pos_lat`, 
        `pos_timestamp`  
   FROM `log_messaging` 
  WHERE `equip_id`='207' AND `tran_type`='T.2.12.0' 
  ORDER BY receipt_ts DESC LIMIT 1 ) 

 UNION  

(SELECT 
       `receipt_ts`, 
       `driver_id`, 
       `equip_id`, 
       `pos_lon`, 
       `pos_lat`, 
       `pos_timestamp`  
  FROM `log_messaging` 
 WHERE `equip_id`='212' AND `tran_type`='T.2.12.0' 
 ORDER BY receipt_ts DESC LIMIT 1 ) 

 UNION

  (SELECT 
         `receipt_ts`, 
         `driver_id`, 
         `equip_id`, 
         `pos_lon`, 
         `pos_lat`, 
         `pos_timestamp`  
    FROM `log_messaging`
   WHERE `equip_id`='213' AND `tran_type`='T.2.12.0' 
   ORDER BY receipt_ts DESC LIMIT 1 );

=================

我正在合并每个返回的行来为多个equip_id 构建一个max(receipt_ts) 的数据集。 (我需要获取设备的最新定位。

有时查询最终会针对 100 多个唯一的equip_id。

我正在尝试使查询比当前执行得更快(如上所述,~100 个 UNION 大约需要 7 秒...

指出正确的方向??

谢谢!

【问题讨论】:

    标签: mysql join union


    【解决方案1】:

    我会使用IN 子句:

    SELECT receipt_ts, driver_id, equip_id, pos_lon, pos_lat, pos_timestamp 
    FROM log_messaging a
    JOIN (SELECT c.equip_id, max(c.receipt_ts) as receipt
          FROM log_messaging c
          WHERE equip_id in ('207', '212', '213')
            AND tran_type='T.2.12.0'
          GROUP by c.equip_id) b USING(equip_id)
    WHERE b.receipt = a.receipt_ts
    ORDER BY a.receipt_ts
    

    请注意,如果您真的想使用UNION(我不明白您为什么会这样做)但又想优化它,您可以使用UNION ALL,它会比UNION 更高效检查数据重复删除会消耗更多进程。

    【讨论】:

    • WHEREequip_id in('207','212','213') .... 这是我想的那种事情,但是查询的设置方式,它只返回单行。有没有办法让它在列表中的每个equip_id 返回一行?
    • 这也不行……现在它返回与列出的equip_ids 匹配的所有行。我应该集成一个 MAX() 语句吗?类似... WHEREequip_id in('207','212','213') AND tran_type='T.2.12.0' ANDreceipt_ts=(SELECT MAX(receipt_ts) WHEREequip_id= ???) ORDER BYreceipt_ts我只是不确定要在 ??? 中添加什么,因为它需要针对每个 MAX 查找进行更改。另外, MAX() 函数似乎很慢?是这样还是只是我的观察?
    • 看起来它可以解决问题,但它返回错误...“'where 子句'中的未知列'a.equip_id'”
    • #1111 - 组函数的使用无效
    • 我刚刚在我的应用程序中用 295 个 id 运行了一个测试,只用了 6 秒。我想我对结果很满意...谢谢你的帮助!
    【解决方案2】:

    首先,您应该使用union all 而不是union。所以从这个查询开始:

    (SELECT receipt_ts, driver_id, equip_id, pos_lon, pos_lat, pos_timestamp
     FROM log_messaging
     WHERE equip_id = '207' AND tran_type = 'T.2.12.0'
     ORDER BY receipt_ts DESC
     LIMIT 1
    ) UNION ALL
    (SELECT receipt_ts, driver_id, equip_id, pos_lon, pos_lat, pos_timestamp
     FROM log_messaging
     WHERE equip_id = '212' AND tran_type = 'T.2.12.0'
     ORDER BY receipt_ts DESC
     LIMIT 1
    ) UNION ALL
    (SELECT receipt_ts, driver_id, equip_id, pos_lon, pos_lat, pos_timestamp
     FROM log_messaging
     WHERE equip_id = '213' AND tran_type = 'T.2.12.0'
     ORDER BY receipt_ts DESC
     LIMIT 1
    ) ;
    

    这是一个合理的查询。我建议您在 log_messaging(tran_type, equip_id, recipt_ts) 上创建一个索引。

    【讨论】:

    • 谢谢,我改用 UNION ALL。我已经在建议的列上有了索引。
    • I tried running the batch query again from my application... when 'select all' is picked, it builds a statement of 295 UNIONS (based on all of the equip_ids)... and it took 28 秒执行。必须有更有效的方法来组合这些?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-23
    • 2011-12-28
    • 1970-01-01
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多