在选择查询中选择查询?

时间:2011-10-14 13:18:26

标签: mysql sql

所以我想逐个月地将新用户与表中的返回用户进行比较。我有一个表,其中包含用户名和日期戳的每个操作。

我可以轻松拉出执行操作的用户,例如2011年1月。要查看每个用户是否是新用户,我需要针对之前的所有记录(2011年1月之前)运行用户名。

在我的摸索中,我想出了以下内容:

  SELECT ini.username,
         MIN(ini.datetime) AS firstAction,
         COUNT(ini.datetime) AS numMonth,
         (SELECT COUNT(*) 
            FROM tableActions tot
           WHERE tot.username = ini.username
             AND tot.datetime < '201101%' 
             AND tot.datetime > '201001%') AS numTotal
    FROM tableActions ini
   WHERE DATETIME >= '201101%' 
     AND DATETIME < '201102%'
GROUP BY ini.username
ORDER BY firstAction

它没有错误,但它也没有完成。似乎非常激烈。

4 个答案:

答案 0 :(得分:5)

您可以重新编写查询(假设tableactions.datetimeDATETIME数据类型):

   SELECT ini.username,
          MIN(ini.datetime) AS firstAction,
          COUNT(ini.datetime) AS numMonth,
          x.numTotal
     FROM tableActions ini
LEFT JOIN (SELECT tot.username,
                  COUNT(*) AS numTotal
             FROM tableActions tot
            WHERE tot.datetime > '2010-01-01'
              AND tot.datetime < '2011-01-01'
         GROUP BY tot.username) x ON x.username = ini.username
    WHERE ini.datetime BETWEEN '2011-01-01' AND '2011-01-31'
 GROUP BY ini.username
 ORDER BY firstAction

尽管使用usernameusername的覆盖索引值得考虑,但可能至少会在datetime上设置索引。

datetime比较看起来很可疑 - LIKE是唯一支持通配符的。

答案 1 :(得分:1)

我认为使用合适的where子句进行简单的表到自身连接就足够了(这个查询直接来自我的头脑,未经测试):

SELECT    curr_activity.username, COUNT(prev_activity.username) AS did_something_in_the_past
FROM      tableActions AS curr_activity
LEFT JOIN tableActions AS prev_activity ON curr_activity.username = prev_activity.username 
WHERE     curr_activity.datetime >= '2011-01-01' AND curr_activity.datetime < '2011-02-01'
AND       prev_activity.datetime <  '2011-01-01' 
GROUP BY  curr_activity.username

索引很重要。您必须为usernamedatetime列编制索引,datetime列必须是datetime或类似的数据类型。

答案 2 :(得分:0)

SELECT username,
MIN(datetime) AS firstAction,
MAX(datetime) AS numMonth,
COUNT(*) AS numTotal
GROUP BY ini.username
HAVING numTotal > 1 
WHERE DATETIME between '201001%' AND '201102%'
ORDER BY username
* I think this collapsed version is what you need ?  

答案 3 :(得分:0)

我认为你可以替换

SELECT COUNT(*) 
        FROM tableActions tot
       WHERE tot.username = ini.username
         AND tot.datetime < '201101%' 
         AND tot.datetime > '201001%'

SELECT 1
        FROM tableActions tot
       WHERE tot.username = ini.username
         AND tot.datetime < '201101%' 
         AND tot.datetime > '201001%' LIMIT 1

,所以它不必遍历所有记录并计算它们。