云服务器网:购买云服务器和VPS必上的网站!

怎样使用MySQL查询一年中每个月的记录数

以下演示将在下表数据中进行:其中:id为主键用于表的连接;value1为需要统计的主体,如用户等;date为记录日期。先说结论
SELECTtmp.value1 AS `value1`,MONTH(SUBSTRING_INDEX(tmp.ct, ,, 1))

以下演示将在下表数据中进行:

其中:id为主键用于表的连接;value1为需要统计的主体,如用户等;date为记录日期。

先说结论

SELECT
tmp.value1 AS `value1`,
MONTH(SUBSTRING_INDEX(tmp.ct, ‘,’, 1)) AS `month`,
LENGTH(tmp.ct) – LENGTH(
REPLACE
(tmp.ct, ‘,’, ”)
) + 1 AS `cnt`
FROM
(
SELECT
id,
value1,
GROUP_CONCAT(date_value) AS ct
FROM
test_year_record
GROUP BY
value1,
INTERVAL(
date_value,
DATE(CONCAT(‘2022’, ‘-01-01’)),
DATE(CONCAT(‘2022’, ‘-02-01’)),
DATE(CONCAT(‘2022’, ‘-03-01’)),
DATE(CONCAT(‘2022’, ‘-04-01’)),
DATE(CONCAT(‘2022’, ‘-05-01’)),
DATE(CONCAT(‘2022’, ‘-06-01’)),
DATE(CONCAT(‘2022’, ‘-07-01’)),
DATE(CONCAT(‘2022’, ‘-08-01’)),
DATE(CONCAT(‘2022’, ‘-09-01’)),
DATE(CONCAT(‘2022’, ‘⑴0-01’)),
DATE(CONCAT(‘2022’, ‘⑴1-01’)),
DATE(CONCAT(‘2022’, ‘⑴2-01’)),
DATE(CONCAT(‘2023’, ‘-01-01’))
)
) AS tmp
JOIN test_year_record AS ot
ON
ot.id = tmp.id
WHERE
ot.value1 = 1 AND YEAR(SUBSTRING_INDEX(tmp.ct, ‘,’, 1)) = ‘2022’

注:以’2022’为例,上面结论中使用了CONCAT方法进行字符串拼接,方便了年份替换,可以直代替换置对应的ORM的参数等。

查询结果

思路及SQL解释

这个问题可以划分为以下几个子问题,我们可以挨个分析解决:

1. 怎么以月份划分

对一个月份的数据可以以下判断:

date_value >= DATE_ADD(date_value, INTERVAL – DAY(date_value) + 1 DAY)
AND
data_value <= LAST_DAY(data_value)

解释一下:

DATE_ADD(date_value, INTERVAL – DAY(date_value) + 1 DAY):data_value所在月的第一天,原理为在data_value的基础上加上-DAY(data_value)天数再+1,固然也能够使用DATE_SUB或去YEAR和MONTH信息再进行拼接;

LAST_DAY(date_value):data_value所在月的最后一天。

一个月的解决了,那末多个月的不过就手写几个范围就能够了(x

固然不能手写这些范围,一方面是很麻烦而且不好看,另外一方面是会给mysql带来过量的计算量。

那末如何给12月进行划分呢:

INTERVAL() 函数可以解决我们的问题:

INTERVAL( N , n 1 , n 2 , ⋯   , n 3 N,n_1,n_2,\cdots,n_3 N,n1​,n2​,⋯,n3​),其中 N N N为带判断是数据,后面的 n 1 ∼ n n n_1 \sim n_n n1​∼nn​分别为各个中断点,这个函数的返回值以下,当 N < n 1 N < n1 N<n1返回0,当 n 1 ≤ N < n 2 n_1 \leq N < n_2 n1​≤N<n2​时返回1,当 n 2 ≤ N < n 3 n_2 \leq N < n_3 n2​≤N<n3​时返回2,…,以此类推。

据此,我们可以给一年做一个分段:

INTERVAL(
date_value,
DATE(CONCAT(‘2022’, ‘-01-01’)), # 一月
DATE(CONCAT(‘2022’, ‘-02-01’)), # 二月
DATE(CONCAT(‘2022’, ‘-03-01’)), # 三月
DATE(CONCAT(‘2022’, ‘-04-01’)), # 四月
DATE(CONCAT(‘2022’, ‘-05-01’)), # 五月
DATE(CONCAT(‘2022’, ‘-06-01’)), # 六月
DATE(CONCAT(‘2022’, ‘-07-01’)), # 七月
DATE(CONCAT(‘2022’, ‘-08-01’)), # 八月
DATE(CONCAT(‘2022’, ‘-09-01’)), # 九月
DATE(CONCAT(‘2022’, ‘⑴0-01’)), # 十月
DATE(CONCAT(‘2022’, ‘⑴1-01’)), # 十一月
DATE(CONCAT(‘2022’, ‘⑴2-01’)), # 十二月
DATE(CONCAT(‘2023’, ‘-01-01’)) # 次年一月,避免次年的数据记录进当年12月中
)

注: 这里其实还有个问题,就是结果会返回去年的数据(0),可以像我一样在外查询里面进行一个年份判断,也能够交给java等检测。

2.获得每个月数据

可使用GROUP BY子句,以INTERVAL的值进行分组(为了保证属于同一个value1的数据,还需要以value1进行分组)。

注:GROUP BY 子句中含有多个参数时,将会是多条这些数据都一样的记录分为一组。

仅仅是做了分组是不够的,我们还需要GROUP_CONCAT()函数来获得一个分组中的数据集。

履行完当前这步,可以获得的结果以下:

3.统计每个月数据

在ct这一列中,我们获得的数据是有规律的,比如一个日期中会有两个"-"、两个日期之间以",“分隔。

这里我们选择以”,"为标志,统计出有多少个分隔符,再+1就得到了数据的数量。

至于实现方式,可使用以下方式:

LENGTH(tmp.ct) – LENGTH(REPLACE(tmp.ct, ‘,’, ”)) + 1

4.统计值与月份相对应

获得GROUP_CONCAT获得的第一个日期便可代表这一全部数据所在的月份。

可使用SUBSTRING_INDEX()函数,它有三个参数,第一个参数为待片取的字符串、第二个参数为分隔符、第三个参数为第几个截取到第几个分隔符。

如此一来:

SUBSTRING_INDEX(tmp.ct, ‘,’, 1)

即可以取到该日期,再使用MONTH函数便可获得对应的月份。

5.整体整合

我这里是使用了一次子查询,子查询获得对应的分组及GROUP_CONCAT数据,再交由外查询进行处理。

结语

这里给出的方案仅仅是一种方案,或许存在着其他更快更好的解决方案但我没有想到,在复杂问题眼前一步一步获得小数据是我习惯,这也就使得极可能出现多个嵌套着的子查询。

到此这篇关于怎样使用MySQL查询一年中每个月的记录数的文章就介绍到这了,更多相关MySQL查询每个月记录数内容请搜索之前的文章或继续浏览下面的相关文章希望大家以后多多支持!

本文来源:https://www.yuntue.com/post/151726.html | 云服务器网,转载请注明出处!

关于作者: yuntue

云服务器(www.yuntue.com)是一家专门做阿里云服务器代金券、腾讯云服务器优惠券的网站,这里你可以找到阿里云服务器腾讯云服务器等国内主流云服务器优惠价格,以及海外云服务器、vps主机等优惠信息,我们会为你提供性价比最高的云服务器和域名、数据库、CDN、免费邮箱等企业常用互联网资源。

为您推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注