[英]Count the number of records per month
I have records with a start and end date, like so: 我有开始日期和结束日期的记录,如下所示:
id start_date end_date
1 2016-01-01 2016-10-31
2 2016-06-01 2016-12-31
3 2016-06-01 2016-07-31
I have to know the number of records that were active per month (or better put: on the first day of all months in a given period). 我必须知道每月活动的记录数(或者更好的方法是:在给定期间内所有月份的第一天)。 The counts would look like this when calculated for 2016:
在为2016计算时,计数看起来像这样:
jan: 1
feb: 1
mar: 1
apr: 1
may: 1
jun: 3
jul: 3
aug: 2
sep: 2
oct: 2
nov: 1
dec: 1
The solution I came up with, is to create a TEMP TABLE with all applicable dates for the given period: 我想到的解决方案是创建一个TEMP TABLE,其中包含给定期间的所有适用日期:
date
2016-01-01
2016-02-01
...
Which makes the query very easy: 这使查询非常容易:
SELECT
COUNT(*),
m.date
FROM
months m
INNER JOIN table t
ON m.date BETWEEN t.start_date AND t.end_date
GROUP BY
m.date
This produces exactly the results I'm looking for. 这将产生我正在寻找的结果。 However;
然而; I do feel as if this could be done easier.
我确实觉得这可以更轻松地完成。 I just don't know how.
我就是不知道
Any suggestions? 有什么建议么?
You can do it the following way, even if it looks ugly: 即使看起来很丑,也可以通过以下方式进行操作:
Assuming you want to run a report and you are only interested in "months of a certain year", the following query might work: 假设您要运行报告,并且只对“某年的月份”感兴趣,则以下查询可能有效:
select m,Count(id) FROM (
SELECT 1 as m UNION
SELECT 2 as m UNION
SELECT 3 as m UNION
SELECT 4 as m UNION
SELECT 5 as m UNION
SELECT 6 as m UNION
SELECT 7 as m UNION
SELECT 8 as m UNION
SELECT 9 as m UNION
SELECT 10 as m UNION
SELECT 11 as m UNION
SELECT 12 as m) AS tabseq
CROSS JOIN x WHERE
(year (start_date) = 2016 AND year (end_date) = 2016 AND m >= month(start_date) AND m <= month(end_date)) -- starts abd ends this year
or
(year (start_date) < 2016 AND year (end_date) = 2016 AND m <= month(end_date)) -- ends this year, consider months until end of contract
or
(year (start_date) < 2016 AND year (end_date) > 2016) -- spans the year, ignore month,
or
(year (start_date) = 2016 AND year (end_date) > 2016 AND m >= month(start_date)) -- starts this year, consider months until end of year
GROUP BY m;
result: 结果:
m count(id)
1 1
2 1
3 1
4 1
5 1
6 3
7 3
8 2
9 2
10 2
11 1
12 1
As suggested in the comments, I replaced the temp table with a permanent table called 'calendar'. 如评论中所建议,我将临时表替换为名为“ calendar”的永久表。
CREATE TABLE `calendar` (
`date` date NOT NULL,
PRIMARY KEY (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
I filled this table with all dates from 2000-01-01 until 2100-12-31. 我用2000年1月1日至2100年12月31日之间的所有日期填写了此表。 I rewrote my query to this:
我将查询重写为此:
SELECT
COUNT(*),
c.date
FROM
calendar c
INNER JOIN table t
ON c.date BETWEEN t.start_date AND t.end_date
WHERE
DAYOFMONTH(c.date) = 1
AND
c.date BETWEEN '2016-01-01' AND '2016-12-31'
GROUP BY
c.date
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.