我有一个包含以下记录的表:
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;
答案 0 :(得分: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;
答案 1 :(得分: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
子句之前,不能在表达式中使用select-list中定义的列别名。实际上,在标准SQL中,在ORDER BY
子句之前不能使用它们,但MySQL也支持在GROUP BY
和HAVING
子句中使用别名。
答案 2 :(得分:0)
将日期转换为查询中的unix时间戳(秒),然后查找差值为&lt; =一个月内的秒数。
您可以在此处找到更多信息: http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_unix-timestamp
如果您需要有关查询的帮助,请告诉我,但MySQL具有很好的处理日期时间的功能。
[编辑]由于我对真正的问题感到困惑,我需要完成草坪,但在我忘记之前我想写下来。
要按天计算数字,你会希望你的where子句如上所述,限制为过去30天,但你需要按天分组,所以选择将每个开始转换为这个月的某一天,然后计算一下。
这假设每次使用将限制在一天,如果开始和结束日期可能跨越几天,则会更加棘手。