2011-10-14 257 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或類似的數據類型。