MySql查询时日期补全(连续)的一种方法

某一日,需要查询订单表中前7天每天的订单数,sql依次写出来:

SELECT
    DATE_FORMAT(order_time,'%Y-%m-%d') date,
    count(*) orderCount
FROM
    order
WHERE
    date_sub(curdate(), INTERVAL 7 DAY) < date(order_time)
GROUP BY DATE_FORMAT(order_time,'%Y-%m-%d')
ORDER BY date ASC

一执行,数据出来了,不过不连续,数量也没有7条,老板生意惨淡,很多时候一天不能来一个单,但程序不能没有数据,所以这里直观的办法就是补上差的数据,怎么补?
第一想到的就是用上层语言来补,比如java:

//从数据库中查询指定天数之前到当前每天的订单数
List<Map<String, Object>> orders= orderDao.queryOrder(7);
//补全数据库中不存在的日期,订单数为0
List<String> dayList = DateUtil.dayList(7, 1,false);//得到7天前到今天每天的日期
boolean exists=false;
for (int i=0;i<dayList.size();i++) {
    exists=false;
    for (Map<String, Object> hs : orders) {
        if (dayList.get(i).equals(hs.get("date"))) {
            exists=true;
            break;
        }
    }
    if(!exists){
        final String date=dayList.get(i);
        orders.add(i,new HashMap<String,Object>(){{
            put("orderCount", 0);
            put("datat", date);
        }});
    }
}
return orders;

ok了,没问题。
转过头,老板说7天业绩看不出我店半年不开张开张吃半年的本质,要求要自定义开始结束时间来查,我说,好嘞您!
不过上面那种方法就存在问题了,真要选2年的日期来查,那得循环多少次啊?于是开动脑筋,由这里得到启发: mysql按日期分组(group by)查询统计的时候,没有数据补0的解决办法,下面来写sql:

SELECT
    od.date,
    od.orderCount
FROM
    (
        SELECT
            DATE_FORMAT(order_time,'%Y-%m-%d') date,
            count(*) orderCount
        FROM
            order
        WHERE
            order_time>'开始时间' and order_time<'结束时间'
        GROUP BY DATE_FORMAT(order_time,'%Y-%m-%d')

        UNION (SELECT 0, '2017-03-01')
        UNION (SELECT 0, '2017-03-02')
        UNION (SELECT 0, '2017-03-03')
        UNION (SELECT 0, '2017-03-04')
        UNION (SELECT 0, '2017-03-05')
        UNION (SELECT 0, '2017-03-06')
        UNION (SELECT 0, '2017-03-07')
        UNION (SELECT 0, '2017-03-08')
        -- 很多个UNION ......
    ) AS od
GROUP BY od.date
ORDER BY od.date ASC

妥了!至于sql中间那一长串的UNION语句,那就根据选择的日期用java生成吧!
估计还有更好的方法,欢迎赐教!

Logo

更多推荐