没有存储过程、临时表,只有一个查询,以及给定日期列索引的高效执行计划:
select
subdate(
'2012-12-31',
floor(dateDiff('2012-12-31', dateStampColumn) / 30) * 30 + 30 - 1
) as "period starting",
subdate(
'2012-12-31',
floor(dateDiff('2012-12-31', dateStampColumn) / 30) * 30
) as "period ending",
count(*)
from
YOURTABLE
group by floor(dateDiff('2012-12-31', dateStampColumn) / 30);
Run Code Online (Sandbox Code Playgroud)
除了这个咒语之外,这里发生的事情应该是非常明显的:
floor(dateDiff('2012-12-31', dateStampColumn) / 30)
Run Code Online (Sandbox Code Playgroud)
该表达式出现多次,其计算结果为 30 天前的周期数dateStampColumnis。dateDiff返回以天为单位的差值,将其除以 30 得到 30 天的周期,并将其全部输入以将floor()其四舍五入为整数。一旦我们有了这个数字,我们就可以得到GROUP BY它,然后我们做一些数学运算,将这个数字转换回该期间的开始和结束日期。
如果您愿意,可以替换'2012-12-31'为。now()这是一些示例数据:
CREATE TABLE YOURTABLE
(`Id` int, `dateStampColumn` datetime);
INSERT INTO YOURTABLE
(`Id`, `dateStampColumn`)
VALUES
(1, '2012-10-15 02:00:00'),
(1, '2012-10-17 02:00:00'),
(1, '2012-10-30 02:00:00'),
(1, '2012-10-31 02:00:00'),
(1, '2012-11-01 02:00:00'),
(1, '2012-11-02 02:00:00'),
(1, '2012-11-18 02:00:00'),
(1, '2012-11-19 02:00:00'),
(1, '2012-11-21 02:00:00'),
(1, '2012-11-25 02:00:00'),
(1, '2012-11-25 02:00:00'),
(1, '2012-11-26 02:00:00'),
(1, '2012-11-26 02:00:00'),
(1, '2012-11-24 02:00:00'),
(1, '2012-11-23 02:00:00'),
(1, '2012-11-28 02:00:00'),
(1, '2012-11-29 02:00:00'),
(1, '2012-11-30 02:00:00'),
(1, '2012-12-01 02:00:00'),
(1, '2012-12-02 02:00:00'),
(1, '2012-12-15 02:00:00'),
(1, '2012-12-17 02:00:00'),
(1, '2012-12-18 02:00:00'),
(1, '2012-12-19 02:00:00'),
(1, '2012-12-21 02:00:00'),
(1, '2012-12-25 02:00:00'),
(1, '2012-12-25 02:00:00'),
(1, '2012-12-26 02:00:00'),
(1, '2012-12-26 02:00:00'),
(1, '2012-12-24 02:00:00'),
(1, '2012-12-23 02:00:00'),
(1, '2012-12-31 02:00:00'),
(1, '2012-12-30 02:00:00'),
(1, '2012-12-28 02:00:00'),
(1, '2012-12-28 02:00:00'),
(1, '2012-12-30 02:00:00');
Run Code Online (Sandbox Code Playgroud)
结果:
period starting period ending count(*)
2012-12-02 2012-12-31 17
2012-11-02 2012-12-01 14
2012-10-03 2012-11-01 5
Run Code Online (Sandbox Code Playgroud)
期间端点包括在内。
在SQL Fiddle中玩这个。
有一点潜在的愚蠢之处在于,任何 30 天的时间段内有零个匹配行都不会包含在结果中。如果您可以将其与周期表连接起来,那么就可以消除这种情况。然而,MySQL 没有像 PostgreSQL 的generate_series()这样的东西,所以你必须在你的应用程序中处理它或者尝试这个聪明的 hack。