如何使用MySQL查询一年中每月的记录数

目录
  • 先说结论
    • 查询结果
  • 思路及SQL解释
    • 1. 如何以月份划分
    • 2.获取每月数据
    • 3.统计每月数据
    • 4.统计值与月份相对应
    • 5.总体整合
  • 结语

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

其中: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', '-10-01')),
            DATE(CONCAT('2022', '-11-01')),
            DATE(CONCAT('2022', '-12-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', '-10-01')), # 十月
            DATE(CONCAT('2022', '-11-01')), # 十一月
            DATE(CONCAT('2022', '-12-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查询每月记录数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • mysql实现查询最接近的记录数据示例

    本文实例讲述了mysql实现查询最接近的记录数据.分享给大家供大家参考,具体如下: 查询场景:现在的需求是查询年龄最接近20岁的用户,获取前5个 我现在的数据库记录用户年龄的字段记录格式是"1995-05-20",字段名称birthday 解决思路: 1.首先查询时转换成用户年龄 日期格式转年龄的方法: (1)当前年份 - 日期格式中的年份 date_format(now(), '%Y') - from_unixtime(unix_timestamp(birthday), '%Y')

  • 如何使用MySQL查询一年中每月的记录数

    目录 先说结论 查询结果 思路及SQL解释 1. 如何以月份划分 2.获取每月数据 3.统计每月数据 4.统计值与月份相对应 5.总体整合 结语 以下演示将在下表数据中进行: 其中:id为主键用于表的连接:value1为需要统计的主体,如用户等:date为记录日期. 先说结论 SELECT tmp.value1 AS `value1`, MONTH(SUBSTRING_INDEX(tmp.ct, ',', 1)) AS `month`, LENGTH(tmp.ct) - LENGTH( REPL

  • MySQL查询两个日期之间记录的方法

    网上搜索出来的结果多是下面答案: MySQL中,如何查询两个日期之间的记录,日期所在字段的类型为datetime(0000-00-00 00:00:00) 解决方案: 直接使用><=就可以查询. where createDate<'2003-5-31' and createDate>'2003-2-30'; 其实简单美好的写法可以是这样的 where createDate between'2010-08-01'  and  '2010-08-19' 看完了之后,你是不是觉得后者比较

  • SQL Server数据库按百分比查询出表中的记录数

    SQL Server数据库查询时,能否按百分比查询出记录的条数呢?答案是肯定的.本文我们就介绍这一实现方法. 实现该功能的代码如下: create procedure pro_topPercent ( @ipercent [int] =0 --默认不返回 ) as begin select top (@ipercent ) percent * from books end 或 create procedure pro_topPercent ( @ipercent [int] =0 ) as be

  • MySQL 如何限制一张表的记录数

    目录 一.触发器解决方案 二.分区表解决方案 三.通用表空间解决方案 关于MySQL 如何限制一张表的记录数,这没有一个简化的答案,比如执行一条命令或者说简单设置一个参数都不能完美解决.接下来我给出一些可选解决方案. 对数据库来讲,一般问题的解决方案无非有两种,一种是在应用端:另外一种是在数据库端. 首先是在数据库端(假设表硬性限制为1W条记录): 一.触发器解决方案 触发器的思路很简单,每次插入新记录前,检查表记录数是否到达限定数量,数量未到,继续插入:数量达到,先插入一条新记录,再删除最老的

  • mysql查询语句中用户变量的使用代码解析

    上一篇文章中我们介绍了MySQL优化总结-查询总条数.这篇文章我们来介绍下查询语句中的另一个知识:用户变量的使用代码解析. 先上代码吧 SELECT `notice`.`id` , `notice`.`fid` , `notice`.`has_read` , `notice`.`notice_time` , `notice`.`read_time` , `f`.`fnum` , `f`.`forg` , `f`.`fdst` , `f`.`actual_parking` AS `parking`

  • PHP访问MySQL查询超时处理的方法

    目前两个客户端扩展库连接超时可以设置选项来操作,比如mysqli: 复制代码 代码如下: <?php //创建对象 $mysqli = mysqli_init(); //设置超时选项 $mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5); //连接 $mysqli->real_connect('localhost', 'my_user', 'my_password', 'world'); //如果超时或者其他连接失败打印错误信息 if (mysq

  • 如何设计高效合理的MySQL查询语句

    MySQL查询语句大家都在用,但是应该如何设计高效合理的MySQL查询语句呢?下面就教您MySQL查询语句的合理设计方法,分享给大家学习学习. 1.合理使用索引 索引是数据库中重要的数据结构,它的根本目的就是为了提高查询效率.现在大多数的数据库产品都采用IBM最先提出的ISAM索引结构.索引的使用要恰到好处,其使用原则如下: ●在经常进行连接,但是没有指定为外键的列上建立索引,而不经常连接的字段则由优化器自动生成索引. ●在频繁进行排序或分组(即进行group by或order by操作)的列上

  • mysql查询语句通过limit来限制查询的行数

    mysql查询语句,通过limit来限制查询的行数. 例如: select name from usertb where age > 20 limit 0, 1; //限制从第一条开始,显示1条 select name from usertb where age > 20 limit 1; //同上面的一个效果 select name from usertb where age > 20 limit 4, 1; //显示从第五条开始,显示1条

  • MySql查询时间段的方法

    本文实例讲述了MySql查询时间段的方法.分享给大家供大家参考.具体方法如下: MySql查询时间段的方法未必人人都会,下面为您介绍两种MySql查询时间段的方法,供大家参考. MySql的时间字段有date.time.datetime.timestamp等,往往我们在存储数据的时候将整个时间存在一个字段中,采用datetime类型:也可能采用将日期和时间分离,即一个字段存储date,一个字段存储时间time.无论怎么存储,在实际应用中,很可能会出现包含"时间段"类型的查询,比如一个访

  • php、mysql查询当天,查询本周,查询本月的数据实例(字段是时间戳)

    php.mysql查询当天,查询本周,查询本月的数据实例(字段是时间戳) //其中 video 是表名: //createtime 是字段: // //数据库time字段为时间戳 // //查询当天: $start = date('Y-m-d 00:00:00'); $end = date('Y-m-d H:i:s'); SELECT * FROM `table_name` WHERE `time` >= unix_timestamp( '$start' ) AND `time` <= uni

随机推荐