SQL查询在日期范围内匹配日期的记录数?

时间:2009-08-15 00:00:50

标签: sql mysql

我有一个包含以下记录的表:

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;

3 个答案:

答案 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_activelast_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 BYHAVING子句中使用别名。

答案 2 :(得分:0)

将日期转换为查询中的unix时间戳(秒),然后查找差值为&lt; =一个月内的秒数。

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

如果您需要有关查询的帮助,请告诉我,但MySQL具有很好的处理日期时间的功能。

[编辑]由于我对真正的问题感到困惑,我需要完成草坪,但在我忘记之前我想写下来。

要按天计算数字,你会希望你的where子句如上所述,限制为过去30天,但你需要按天分组,所以选择将每个开始转换为这个月的某一天,然后计算一下。

这假设每次使用将限制在一天,如果开始和结束日期可能跨越几天,则会更加棘手。