mysql中的年,月,日统计以及日历表的实现

上周被任命一个统计接口的实现。
其实单纯的统计查询很简单的,分组加聚合函数一般就能搞定了,但是问题是补0问题。
正常的统计查询:


单纯的统计查询

但是这个放在需求上大多数时候都是满足不了的!因为一般这种统计前端都是图表展示,你就这么孤零零的两条数据,不想打架的话还是得老老实实处理一下的。
这个处理分两种:

  1. 代码中遍历循环,我同事就采用了这种方法。据说是采用1-31遍历循环的,不过我手里没有源码,所以不确定具体的实现方法,反正听说是一个月固定31天,比如2月,2,4,9,11之类的,也是31天,不知道最后展现 的结果前台怎么实现的。
    但是我虽然没用代码实现过,但是猜测应该是可以解决这个月份的天数问题吧?不过又要判断年,又要判断月,实现是可以实现,估计也挺麻烦、注意是麻烦不是困难,一层层判断呗。
  2. 这个也是我实现的方法:日历类
    在数据库中添加一个日历表,用来使每一天都有记录,当天没数据则count是0。这个也就是上文中说的补0.
    可能听起来这个比较麻烦,改动还大,毕竟要添加一张表,但是其实没想的那么复杂,毕竟现在网络上这种轮子都有(往下的操作好多是看帖子学的,不过因为是上周实现,很多代码不知道出处了,所以不注明来自于)。而且好多时候我们统计的不仅仅是一种数据,可能涉及到好多种,比如司机啊,注册用户量啊,订单量啊之类之类的,而一个日历类可以应用于所有的统计,甚至包括年月日的统计,真的,我非常推荐这种日历表的方法。

日历表的实现

  • 创建日历表脚本
    首先,日历表的创建和数据的插入如果自己手写,确实麻烦的不行,但是刚刚说的前人的轮子也不是吃素的,如下脚本:
CREATE TABLE num (i int);-- 创建一个表用来储存0-9的数字
INSERT INTO num (i) VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);-- 生成0-9的数字,方便以后计算时间
 
CREATE TABLE  if not exists calendar(datelist date); -- 生成一个存储日期的表,datalist是字段名
 
-- 这里是生成并插入日期数据
INSERT INTO calendar(datelist) SELECT
    adddate(
        (   -- 这里的起始日期,你可以换成当前日期
            DATE_FORMAT("2018-1-1", '%Y-%m-%d') 
        ),
        numlist.id
    ) AS `date`
FROM
    (
        SELECT
            n1.i + n10.i * 10 + n100.i * 100 + n1000.i * 1000+ n10000.i * 10000 AS id
        FROM
            num n1
        CROSS JOIN num AS n10
        CROSS JOIN num AS n100
        CROSS JOIN num AS n1000
        CROSS JOIN num AS n10000
    ) AS numlist;

直接复制粘贴,然后运行就ok了!因为我用的Navicat,所以更是方便的不行:

运行结果

运行完成后,我们刷新下列表:


如上所示

日历表就是我们所需要用的表,而num这个表是工具表,此时可以删除了。这时我们打开这个calendar表:


calendar表数据

从2018年开始,到2291年结束。二百多年的日历,别说用到辞职了,用到我死都绰绰有余。而且还可以酌情删除一部分数据,比如我是19年10月开发的,在之前的 数据不会统计,所以还可以删除2019-09包括之前的数据,至于往后截取时间,看你心情咯。
  • 使用这个日历表查询
    其实这个日历表就是为了查询补0的,所以在查询的时候要关联查询
    其实之前我做的时候都一路顺风,但是这一步却卡了一会儿, 最后还是在我一个好友的帮助下完成的,在此感谢我好友一波。同时深感sql功底薄弱,面壁三秒。
    在这我把sql语句贴出来供大家参考:
按日期统计:
SELECT
    c.datelist as date,
    COUNT(b.id) as count
FROM
    calendar AS c
LEFT JOIN (
    SELECT
        *
    FROM
        driver -- 真正想统计的表名
    WHERE
        lnvalid = 2 -- 这个是查询条件,你们酌情写自己的
    AND flag = 0 -- 这个是查询条件,你们酌情写自己的
) AS b ON c.datelist = DATE(b.create_time)  -- 两个表的关联,因为我表中crate_time是年月日时分秒的,所以要格式化后相等
WHERE
    c.datelist LIKE '2019-10%'       -- 这个是查询某月的日期统计,在代码中这块应该是一个参数。我这里查询的2019年10月份的统计
GROUP BY
    datelist  -- 这个分组按照日期分组,再次声明这个是天的,如果月的这里会不同
ORDER BY
    datelist   -- 这个排序是因为之前一次测试有count的在上面,没有的在下面,日期没有顺序,所以我又升序排了下。

我一如既往的风格,注解墨迹的不行,大家对付看吧,毕竟总比没注释让人摸不着头脑强。

按月份统计:
SELECT
    DATE_FORMAT(c.datelist, '%Y-%m') as date, -- 查询的是年-月,所以要格式处理
    COUNT(b.id) as count
FROM
    calendar AS c
LEFT JOIN (
    SELECT
        *
    FROM
        driver -- 真正想统计的表名
    WHERE
        lnvalid = 2 -- 这个是查询条件,你们酌情写自己的
    AND flag = 0 -- 这个是查询条件,你们酌情写自己的
) AS b ON c.datelist = DATE(b.create_time)  -- 两个表的关联,因为我表中crate_time是年月日时分秒的,所以要格式化后相等
WHERE
    c.datelist LIKE '2019%'      -- 这个是查询某月的日期统计,在代码中这块应该是一个参数。我这里查询的2019年的统计
GROUP BY
    DATE_FORMAT(c.datelist, '%Y-%m')-- 这个分组按照月份分组的,因为datelist是年月日,所以要格式化处理成年月
ORDER BY
    datelist   -- 这个排序是因为之前一次测试有count的在上面,没有的在下面,日期没有顺序,所以我又升序排了下。
按照年统计:
SELECT
    DATE_FORMAT(c.datelist, '%Y') as date, -- 查询的是年,所以要格式处理
    COUNT(b.id) as count
FROM
    calendar AS c
LEFT JOIN (
    SELECT
        *
    FROM
        base_driver -- 真正想统计的表名
    WHERE
        if_lnvalid = 2 -- 这个是查询条件,你们酌情写自己的
    AND flag = 0 -- 这个是查询条件,你们酌情写自己的
) AS b ON c.datelist = DATE(b.create_time)  -- 两个表的关联,因为我表中crate_time是年月日时分秒的,所以要格式化后相等
GROUP BY
    DATE_FORMAT(c.datelist, '%Y')-- 这个分组按照月份分组的,因为datelist是年月日,所以要格式化处理成年
ORDER BY
    datelist   -- 这个排序是因为之前一次测试有count的在上面,没有的在下面,日期没有顺序,所以我又升序排了下。

至此,三个常用的统计查询完成。因为我是多个统计,所以剩下的就是将不同的表与此日历表联合查询啦。
此文仅讲mysql中补0的实现,下一篇讲java代码的实现步骤。
我有一个梦想,若干年后,不管遇到什么问题,翻翻自己的简书,在上面都能找到答案,哈哈,做梦都要笑醒了。所以哪怕为了实现这个梦想,我也愿意事无大小,学到了就记录起来。毕竟我相信文字不会骗人,若干年后,再遇到这样的问题,记忆可能会淡忘,但是我记录的文章是实实在在的啊~
全文手打不易,如果稍微帮到你了,请点个喜欢点个关注支持一下~~~~~也祝大家工作顺顺利利!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,110评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,443评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,474评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,881评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,902评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,698评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,418评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,332评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,796评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,968评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,110评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,792评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,455评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,003评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,130评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,348评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,047评论 2 355

推荐阅读更多精彩内容

  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 5,320评论 0 9
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,988评论 6 13
  • --- layout: post title: "如果有人问你关系型数据库的原理,叫他看这篇文章(转)" date...
    蓝坠星阅读 793评论 0 3
  • 古人云:“三十而立”,所以我一直觉得三十岁是个很神奇的年纪,仿佛所有的问题到了三十岁自然而然就解决了。事实上,三十...
    爱文字的心理人阅读 179评论 1 2
  • 他们就这样一步一步的走,一步一步的走…… 18岁的年龄,永远定格在了长征的路上……
    世界在你手中阅读 259评论 1 2