2009-08-15 178 views
2

我有一個表看起來像這樣的記錄:SQL查詢記錄日期範圍內匹配日期的記錄數量?

CREATE TABLE sample (
    ix int unsigned auto_increment primary key, 
    start_active datetime, 
    last_active datetime 
); 

我需要知道多條記錄是如何活躍在各個的最後30天。日子也應該排序遞增,以便他們返回最舊到最新。

我使用的MySQL和查詢將從PHP運行,但我並不真的需要PHP代碼,只是查詢。

這裏是我的起點:

SELECT COUNT(1) cnt, DATE(?each of last 30 days?) adate 
FROM sample 
WHERE adate BETWEEN start_active AND last_active 
GROUP BY adate; 

回答

5

做一個外連接。

沒有表?製作一張桌子。我總是爲此保留一張虛擬桌子。

create table artificial_range( 
    id int not null primary key auto_increment, 
    name varchar(20) null) ; 

-- or whatever your database requires for an auto increment column 

insert into artificial_range(name) values (null) 
-- create one row. 

insert into artificial_range(name) select name from artificial_range; 
-- you now have two rows 

insert into artificial_range(name) select name from artificial_range; 
-- you now have four rows 

insert into artificial_range(name) select name from artificial_range; 
-- you now have eight rows 

--etc. 

insert into artificial_range(name) select name from artificial_range; 
-- you now have 1024 rows, with ids 1-1024 

現在使它方便使用,並且其限制爲30天,以期:

編輯:JR Lawhorne指出:

你需要改變 「DATE_ADD」 到「 date_sub「在創建的視圖中獲取前30天。

謝謝JR!

create view each_of_the_last_30_days as 
select date_sub(now(), interval (id - 1) day) as adate 
from artificial_range where id < 32; 

現在,在您的查詢中使用這個(我沒有實際測試查詢,我只是假設它工作正常):

編輯:我應該加入另一種方式:

SELECT COUNT(*) cnt, b.adate 
FROM each_of_the_last_30_days b 
left outer join sample a 
on (b.adate BETWEEN a.start_active AND a.last_active) 
GROUP BY b.adate; 
+0

您需要將「date_add」更改爲「date_sub」才能在創建的視圖中獲得前30天。 – 2009-08-15 02:46:43

0

SQL是相互匹配的存儲在數據庫中的值很大,但它並沒有那麼大的匹配值的集合是在數據庫。所以,一個簡單的解決方法是創建一個包含你所需要的值的臨時表:

CREATE TEMPORARY TABLE days_ago (d SMALLINT); 
INSERT INTO days_ago (d) VALUES 
    (0), (1), (2), ... (29), (30); 

現在你可以比較是d天前就start_active和每行的last_active之間的跨度的日期。計算每個值爲d的組中匹配的行數,並且您的計數。

SELECT CURRENT_DATE - d DAYS, COUNT(*) cnt, 
FROM days_ago 
LEFT JOIN sample ON (CURRENT_DATE - d DAYS BETWEEN start_active AND last_active) 
GROUP BY d 
ORDER BY d DESC; -- oldest to newest 

另注:不能使用在選擇列表中的表達式定義的列別名,直到你到GROUP BY條款。實際上,在標準SQL中,直到ORDER BY子句才能使用它們,但MySQL支持在GROUP BYHAVING子句中使用別名。

0

將日期轉換爲查詢中的unix時間戳,即秒,然後查找差異爲< =一個月中的秒數。

你可以在這裏找到更多的信息: http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_unix-timestamp

如果您需要查詢,請讓我知道有幫助,但MySQL有很好的功能,用於處理日期時間。

[編輯]由於我對於真正的問題感到困惑,我需要完成草坪,但在我忘記之前我想寫下來。

要按天數計算您希望您的where子句如上所述,以限制爲過去30天,但您需要按天分組,並且選擇轉換每個開始到一個月的某一天,然後對這些數字進行計數。

這假設每次使用將被限制爲一天,如果開始日期和結束日期可以跨越幾天,則會更棘手。

+0

將哪個日期轉換爲unix時間戳? 'CURRENT_DATE - INTERVAL 30 DAY','start_active'或'end_active'?這如何幫助OP組對最近30次的每一天的活躍記錄*計數? – pilcrow 2009-08-15 01:47:27

+0

將start_active和last_active轉換爲unix_timestamp,或者,雖然我沒有嘗試過,但可以使用subtime()來減去時間,然後轉換,或者,在我上面建議的頁面中,可以使用類似下面的內容:select ID從MESSAGE where SENT_TIME <(CURDATE() - INTERVAL 5 DAY);無論如何,只需查看時間函數,就能找到最適合您的工作。 – 2009-08-15 02:06:28

+0

@詹姆斯布萊克,你的回答措辭表明你認爲OP希望知道與30天的時間窗重疊的記錄數 - 但這是錯誤的問題,他希望每天都知道重疊記錄的數量*在過去的30天。 (是的,日期算法在SQL本地類型中很容易,或者使用整數時代戳。)也許您可以發佈代碼解決方案來說明您的提議? – pilcrow 2009-08-15 04:50:59