我有一张开始日期和结束日期表 - 大多数是一整年,但从任何一个月开始。
我想获得一份关于每年当月活跃行数的报告。它将像计数 - 当前,计数去年,计数2年前等
我在PHP中构建我的查询,因此我可以轻松地使用sum(在结束时的情况)和硬编码的日期或子查询的总和,但我认为可能有更好的方法。有什么想法吗?
答案 0 :(得分:2)
您可以使用表达式而不是“日期中的硬代码”
要返回当前月份的第一个日期,您可以使用一个表达式返回当前日期的年份和月份,并使用固定值替换当月的第一个日期,如下所示:
DATE_FORMAT(NOW(),'%Y-%m-01')
要在那之前一年
DATE_FORMAT(NOW(),'%Y-%m-01') - INTERVAL 1 YEAR
对于范围比较,要检查是否存在“重叠”(表中每行的start_date
和end_date
之间的时间段),以及给定月份的第一天和最后一天,我会做这样的事情:
end_date >= DATE_FORMAT(NOW(),'%Y-%m-01')
AND start_date < DATE_FORMAT(NOW(),'%Y-%m-01') + INTERVAL 1 MONTH
此模式(大于或等于月的第一个月且小于下个月的第一个月)适用于日期以及包含时间组件的日期时间。 (此检查假定end_date的NULL值未用于表示“无结束日期”...需要调整检查以适应该值。)
如果我有规范(正如我解释的那样),我可能会这样做:
SELECT SUM( t.start_date < DATE_FORMAT(NOW(),'%Y-%m-01') + INTERVAL 1 MONTH
AND t.end_date >= DATE_FORMAT(NOW(),'%Y-%m-01') + INTERVAL 0 MONTH
) AS `count_current_year`
, SUM( t.start_date < DATE_FORMAT(NOW(),'%Y-%m-01') + INTERVAL -11 MONTH
AND t.end_date >= DATE_FORMAT(NOW(),'%Y-%m-01') + INTERVAL -12 MONTH
) AS `count_previous_year`
, SUM( t.start_date < DATE_FORMAT(NOW(),'%Y-%m-01') + INTERVAL -23 MONTH
AND t.end_date >= DATE_FORMAT(NOW(),'%Y-%m-01') + INTERVAL -24 MONTH
) AS `count_two_years_ago`
FROM mytable t
我不知道这更好。 (这可能比你拥有的更加丑陋,但我不认为那里有什么东西是残酷的。)
我没有看到在start_date
或end_date
上有效使用索引的方法(给定一行代表“日期范围”),除非完全可以从索引中完成查询(即存在覆盖指数。)
答案 1 :(得分:0)
对于它的价值,您可以使用此字符串检索当月发生任何DATE
,DATETIME
或TIMESTAMP
项目的第一天。
DATE(DATE_FORMAT(when, '%Y-%m-01'))
这个小函数在GROUP BY
表达式等中非常有用。