开发者

Mysql nested query optimization

开发者 https://www.devze.com 2023-02-28 22:55 出处:网络
I have a table that logs variou开发者_高级运维s transactions for a CMS. It logs the username, action, and time. I have made the following query to tell me how many transactions each user made in the p

I have a table that logs variou开发者_高级运维s transactions for a CMS. It logs the username, action, and time. I have made the following query to tell me how many transactions each user made in the past two days, but it is so slow its faster for me to send a bunch of separate querys at this point. Am I missing a fundamental rule for writing nested queries?

SELECT DISTINCT
    `username`
   , ( SELECT COUNT(*)
       FROM `ActivityLog`
       WHERE `username`=`top`.`username`
         AND `time` > CURRENT_TIMESTAMP - INTERVAL 2 DAY
     ) as `count`
FROM `ActivityLog` as `top`
WHERE 1;


You could use:

   SELECT username
        , COUNT(*) AS count
   FROM ActivityLog
   WHERE time > CURRENT_TIMESTAMP - INTERVAL 2 DAY
   GROUP BY username

An index on (username, time) would be helpful regarding speed.


If you want users with 0 transcations (the last 2 days), use this:

SELECT DISTINCT
    act.username
  , COALESCE(grp.cnt, 0) AS cnt
FROM ActivityLog act
  LEFT JOIN
    ( SELECT username
           , COUNT(*) AS count
      FROM ActivityLog
      WHERE time > CURRENT_TIMESTAMP - INTERVAL 2 DAY
      GROUP BY username
    ) AS grp
  ON grp.username = act.username 

or, if you have a users table:

SELECT 
    u.username
  , COALESCE(grp.cnt, 0) AS cnt
FROM users u
  LEFT JOIN
    ( SELECT username
           , COUNT(*) AS count
      FROM ActivityLog
      WHERE time > CURRENT_TIMESTAMP - INTERVAL 2 DAY
      GROUP BY username
    ) AS grp
  ON grp.username = u.username 

Another way, similar to yours, would be:

   SELECT username
        , SUM(IF(time > CURRENT_TIMESTAMP - INTERVAL 2 DAY, 1, 0))
          AS count
   FROM ActivityLog
   GROUP BY username

or even this (because true=1 and false=0 for MySQL):

   SELECT username
        , SUM(time > CURRENT_TIMESTAMP - INTERVAL 2 DAY)
          AS count
   FROM ActivityLog
   GROUP BY username


No need for nesting...

SELECT `username`, COUNT(`username`) as `count` FROM `ActivityLog` WHERE `time` > CURRENT_TIMESTAMP - INTERVAL 2 DAY GROUP BY `username`

Also don't forget to add an INDEX on time if you want to make it even faster

0

精彩评论

暂无评论...
验证码 换一张
取 消