优化SELECT {OTHER_COLUMNS} IN MAX .... GROUP BY语句

时间:2012-09-28 15:30:03

标签: mysql join group-by max subquery

如果你发出这样的查询,我很熟悉MySQL所遇到的问题:

SELECT `user_log`.`USER_NAME`, MAX(`user_log`.`ACCESS_DATE_TIME`), `user_log`.`COMPUTER_NAME`, `user_log`.`LOCATION`  
    FROM `user_log` 
    GROUP BY `user_log`.`USER_NAME` 
    ORDER BY `user_log`.`ACCESS_DATE_TIME` DESC

这不会像您想象的那样返回与MAX ACCESS_DATE_TIME相关联的COMPUTER_NAME和LOCATION。它将返回由GROUP BY列(所有USER_NAME)定义的集合中的第一个值。

因此,为了解决这个问题,我试图构建一个查询链接MAX ... GROUP BY sql,并选择我需要的所有列,其中USER_NAME和ACCESS_DATE_TIME属于被抓取的集合使用MAX ... GROUP语句。

这就是我所拥有的 - >

SELECT `user_log`.`USER_NAME`, `user_log`.`ACCESS_DATE_TIME`, `user_log`.`COMPUTER_NAME`, `user_log`.`LOCATION` 
FROM `user_log`.`user_log` 
JOIN (SELECT `user_log`.`USER_NAME`, MAX(`user_log`.`ACCESS_DATE_TIME`) as sub_max 
    FROM `user_log` 
    GROUP BY `USER_NAME` 
    ORDER BY sub_max DESC) as sub
WHERE (`user_log`.`USER_NAME` = sub.`USER_NAME` AND `user_log`.`ACCESS_DATE_TIME` = sub.sub_max)

然而,它不是很快......有没有更好的方法来做到这一点?我确信有人现在想出了一些东西......

2 个答案:

答案 0 :(得分:1)

将性能与临时表进行比较(未经测试):

CREATE TEMPORARY TABLE `user_log_temp` ENGINE=memory
SELECT `user_log`.`USER_NAME`, MAX(`user_log`.`ACCESS_DATE_TIME`) as sub_max 
FROM `user_log` 
GROUP BY `USER_NAME`;

SELECT `user_log`.`USER_NAME`, `user_log`.`ACCESS_DATE_TIME`, `user_log`.`COMPUTER_NAME`, `user_log`.`LOCATION` 
FROM `user_log`.`user_log` 
JOIN `user_log_temp` as sub 
  ON `user_log`.`USER_NAME` = sub.`USER_NAME`
  AND `user_log`.`ACCESS_DATE_TIME` = sub.sub_max;

DROP TABLE `user_log_temp`;

答案 1 :(得分:0)

这是我最终实施的目标 - >

使用MAX ... GROUP BY关系创建表格 - >

CREATE TABLE `user_log_max`
   SELECT
     `USER_NAME`, 
      /* Alias this calculated value as ACCESS_DATE_TIME */
      MAX(`ACCESS_DATE_TIME`) AS `ACCESS_DATE_TIME` 
   FROM `user_log`
   GROUP BY `USER_NAME`

获取所有数据 - >

SELECT DISTINCT `user_log`.`COMPUTER_NAME`, `user_log`.`LOCATION`, `user_log`.`USER_NAME`, `user_log`.`ACCESS_DATE_TIME` 
FROM `user_log`, `user_log_max`
WHERE `user_log_max`.`USER_NAME` = `user_log`.`USER_NAME` AND `user_log_max`.`ACCESS_DATE_TIME ` = `user_log`.`ACCESS_DATE_TIME`

确保添加正确的索引,否则它仍然会很慢。

如果你愿意,你也可以在完成后放弃桌子,因为随着时间的推移它不会相关 - >

DROP TABLE `user_log_max`