vlambda博客
学习文章列表

Mysql输出连续日期的3种写法

之前,小骨想要写代码统计某个固定日期当天未完成的所有订单数。


苦于无法用某个字段来表示这个固定日期,代码迟迟写不出来,总是写进死循环。


写完上篇《》后,小骨灵光一闪,可以用union来连接这些日期啊。


于是写出了以下代码:


SELECT temp FROM(SELECT CURRENT_DATE temp UNION SELECT DATE_SUB(CURRENT_DATE,INTERVAL 1 day) temp UNIONSELECT DATE_SUB(CURRENT_DATE,INTERVAL 2 day) temp UNIONSELECT DATE_SUB(CURRENT_DATE,INTERVAL 3 day) temp UNIONSELECT DATE_SUB(CURRENT_DATE,INTERVAL 4 day) temp UNIONSELECT DATE_SUB(CURRENT_DATE,INTERVAL 5 day) temp UNIONSELECT DATE_SUB(CURRENT_DATE,INTERVAL 6 day) temp ) date_t


成果如下。



如果需要调整日期,就手动改下代码好了。


虽然方法是笨笨的,但好歹攻克了固定日期的难题啊!


结果在兴高采烈的档口立马被慎M泼了一盆冷水,


“如果要统计多天的数据,例如30天,岂不是要插入很多条数据?”


虽然以“符合我的使用习惯就好啦”的理由怼回去了,


但还是不甘心地去查找更好的解决方案,


功夫不负有心人!居然被我找到了3种!


Mysql输出连续日期的3种写法
方法一:通过现UNION构建数据条


SELECT DATE_FORMAT(DATE_SUB(CURRENT_DATE(), INTERVAL sq DAY), '%Y-%m-%d'as dateFROM (SELECT @sq:=@sq+1 as sq from(SELECT 1 UNION SELECT 2 UNION SELECT 3) sq1,(SELECT 1 UNION SELECT 2) sq2,(SELECT @sq:=-1) sq0) date_table


Mysql输出连续日期的3种写法


这段代码以虚拟表数据条的方式,可以一次性给出3*2=6个日期。


同理,可以一次性给出x*y个日期。


而且通过修改“@sq=”后的数值可以调整起始日期。


例如,@sq=0时,数据就是从“2021-01-26”开始,向后推6天。


Mysql输出连续日期的3种写法


这里需要简单地解释一下其中的特殊语句。


SELECT @i := 0 表示“从0开始”。

@i := @i + 1 表示“依次递增”。


所以,这两个语句联用,就是一组循环语句。

循环的次数则由3*2的数据条决定。


(至于为什么两个表以逗号相连是个数据条,我还没闹明白)


如果单独跑以下代码,


SELECT @sq:=@sq+1 as sq from(SELECT 1 UNION SELECT 2 UNION SELECT 3) squ1,(SELECT 1 UNION SELECT 2) squ2,(SELECT @sq:=-1) squ0


结果是一个0至5的数列。


Mysql输出连续日期的3种写法


再把这个数列带入“DATE_SUB(CURRENT_DATE(), INTERVAL sq DAY)”,


就得出了从今天至5天前的一组数列。


这个方法相比于我之前的那个手动加n个UNION已经简化了一大步。


但还是有点不方便,如果我不是要6天,而是31天呢?


31是个质数,没法以数据条的形式来表示。


没关系,再看下一个方法。


Mysql输出连续日期的3种写法
方法二:通过现有数据表和limit生成任意连续日期


SELECT DATE_FORMAT(DATE_SUB(CURRENT_DATE(),INTERVAL sq DAY), '%Y-%m-%d'as dateFROM(SELECT @sq:=@sq+1 as sq FROM(SELECT * from tb_m_m limit 30)squ1, (SELECT @sq:=-1) squ0 ) AS date_table

这个方法和上一个类似,只是把3*2的数据条替换为一个在一张现有表里截图任意行。


依旧是用“@sq=”后的数值来控制起始日期。


修改limit后的数值即可指定任意连续天数。


Mysql输出连续日期的3种写法
方法三: 通过现有数据表和指定日期生成任意连续日期


SELECT DATE_FORMAT(DATE_SUB('2021-01-26', INTERVAL sq DAY), '%Y-%m-%d') AS dateFROM(SELECT @sq :=@sq + 1 AS sqFROM tb_m_m,(SELECT @sq := -1) tempWHERE ADDDATE('2021-01-20',INTERVAL @sq DAY) < DATE_FORMAT('2021-01-26', '%Y-%m-%d') )AS date_table



用这个语句,可以把‘2021-01-20’这种具体日期替换成参数,手动传参。


可以结合metabase的filter使用。


这样就没有任何日期数量限制啦!


唯独需要注意一点~


那就是from的现有数据表里的数据条数要多余连续日期天数!