sql 语言 groupBy 分组统计时间段解决方案
记录一下数据统计时遇到的问题和解决方案
先贴完整的效果
问题一 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表
这个时间我们拿到了日期表,用日期表做主表,左联一下就能解决问题一
问题二 使用了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 协议》,转载必须注明作者和本文链接
推荐文章: