2011-10-14 213 views
2

所以我想按月比较新用户和表中的用户。我有一个表,其中包含每个行动与用户名和日期戳。在选择查询中选择查询?

我可以很容易地拉,在执行的操作,例如用户,2011年1月要查看是否每个用户都是新的,我需要再对所有以前的记录(2011年1月之前)运行他们的用户名。

在我fumblings我想出了以下内容:

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 

它没有错误,但它并没有完成任何。似乎相当激烈。

+0

什么是你的问题?如何“修复”它?陈述你的要求。 –

+0

'datetime'列的数据类型是...'varchar'?馊主意。你的查询*应该会很慢。如果datetime列的数据类型是'datetime',那么我就不明白'> ='201101%'是什么样的比较? –

+0

同意,“datetime”的列声明是什么? – pilcrow

回答

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 

可能有助于至少有上username索引,但覆盖索引使用usernamedatetime值得考虑。

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

+0

有相同的想法 - 计数(日期时间)? – Mike

+0

datetime是varchar。我应该努力解决这个问题,然后尝试运行查询吗?谢谢。 –

+0

不能说如果查询将按原样工作,但这个想法是正确的。顺便说一句,你可以使用'COUNT(1)'而不是'COUNT(*)'。 –

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 ? 
+0

有不同的日期标准 - 可能是拼写错误,否则我同意 –

0

我认为你可以

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

更换

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

,所以它不会通过所有的记录都循环和计数。

+0

'TOP'是SQL Server特定的 –

+0

是的,TOP是针对SQL Server的,因此您需要在子查询的末尾使用'LIMIT 1' 。我不是MySql的大专家,所以只是假设它会工作。 – Bulat

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或类似的数据类型。