sql 语言 groupBy 分组统计时间段解决方案

记录一下数据统计时遇到的问题和解决方案

先贴完整的效果
sql语言groupBy分组统计时间段相关解释方案

问题一 GroupBy数据不是每天连续的

统计图是关于某段时间内,每年/每月/每周的微博数量的折线图。数据为连续不断的,但现实的情况中数据库里的数据不可能是连续的,情况如下

sql语言groupBy分组统计时间段相关解释方案

数据中4号 ~ 7号的时间段没有返回,我们理想中的返回格式是补全没有的日期,然后在这个日期对应的数量字段填0。

在网上google了一下,解决方案是新建一张自期表做主表,左联要统计的表,

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("2016-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;

运行sql语句后,请删除num表
这个时间我们拿到了日期表,用日期表做主表,左联一下就能解决问题一

sql语言groupBy分组统计时间段相关解释方案

问题二 使用了left join,where是针对左表,但左表是日期表,那如何做业务表上的条件限制

原因分析:

数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户;

where条件是在临时表生成好后,再对临时表进行过滤的条件;

因此:where 条件加上,已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。

解决方案是把限制条件放在on后面

select a.*,b.*
from table1 a
left join table2 b on b.X=a.X and XXX

结论:


where后面:是先连接然生成临时查询结果,然后再筛选

on后面:先根据条件过滤筛选,再连 生成临时查询结果

结语

水平有限,关于补0的那个问题其实还想到查询出来用php循环补全日期和补0,但是业务上有很多处要用到这个,用php的话代码量很多,所以了新建日期表这个方案,如果有好的方案希望大家贴上来,多多交流。

本作品采用《CC 协议》,转载必须注明作者和本文链接
未经允许禁止转载 -- 苦力小林,
本帖由系统于 4年前 自动加精
讨论数量: 5

学到了,之前我也遇到过这种情况,都是直接用php来重写缺失代码的。

4年前 评论

@dengminfeng 也是一种解决方法,多多交流吧

4年前 评论

能用ORM的查询法展示一次吗

4年前 评论

@cassieyi 等我有空,最近项目有点紧

4年前 评论

我也等个ORM的写法

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!