设为首页 收藏本站
查看: 363|回复: 0

[经验分享] Mysql 中使用DATE_FORMAT函数按月、周统计数据

[复制链接]

尚未签到

发表于 2016-10-23 09:04:05 | 显示全部楼层 |阅读模式
  项目中的统计报表作的很多,需求中有按周、月统计数据的。查看了Mysql的API,发现Date_format是格式化日期的,看了Date_format()的具体说明后就用这个函数按周统计,sql大致如下:
  select DATE_FORMAT(check_date ,'%X-%V') dates,avg(weight)/10000 weight from ho_body where user_id=295
  and weight >0 and check_date between '2009-02-24' and '2010-02-24' group by dates
  ------------------------------------------------------------------------------------------------------
  查出的结果为:
  dates weight
  2009-30 80.9
2009-31 80.425
2009-32 80.76666667
2009-33 80.75384615
2009-34 80.8
2009-35 79.88
2009-36 80.06
2009-37 79.875
2009-3879.075
2009-39 79.26666667
2009-40 79.16666667
2009-41 78.875
2009-42 78.33333333
2009-43 78.77272727
2009-44 77.625
2009-45 77.825
2009-46 77.575
2009-47 77.45
2009-48 81.25
2009-49 76.5
2009-50 77.83333333
2009-52 79.8
2010-02 79.2

  
  
  %X
  年,其中的星期日是周的第一天,4 位,与 %V 使用
  %x
  年,其中的星期一是周的第一天,4 位,与 %v 使用
  %Y
  年,4
  %y
  年,2 位
  
  难道%X只能与%V一起用表示年-周,并且周日为一周开始,
  %x与%v一起用,表示年-周,周一为一周开始?
  再看到前面的
  
  %V
   (01-53) 星期日是一周的第一天,与 %X使用
  %v
   (01-53) 星期一是一周的第一天,与 %x使用
  看来是这个意思了,我之前怎么就没有注意到这个特别之处呢?可能是当时作完以周统计,然后再写月统计时,一看m表示月,数值,就直接把Date_format('%X-%V')改为Date_format('%X-%m')了。再加上%Y年,4位,%m月,没有具体说明,所以一直没有发现,并且用%X-%m按月统计,测试了许多数据,发现年-月,数值全是正确的。结果在跨年的情况下有问题了。。。一般情况下我是会考虑跨年的情况的,比如在求一个日期属于这一年的第几周,在这个问题上,我测试2009-12-31,2010-01-01属于哪一周,2010-01-03是哪一周,发现之前的方法有bug,后来作了修正才正确。而这是用mysql函数统计,测试一些数据没问题就觉得ok了,根本没有想到这样写在跨年时有问题了。。。。
  
  为了将这个问题彻底整理清楚,下面是我找到的详细解读:
  Date_format可以使用的格式有:
  
  格式
  描述
  %a
  缩写星期名
  %b
  缩写月名
  %c
  月,数值
  %D
  带有英文前缀的月中的天
  %d
  月的天,数值(00-31)
  %e
  月的天,数值(0-31)
  %f
  微妙
  %H
  小时 (00-23)
  %h
  小时 (01-12)
  %I
  小时 (01-12)
  %i
  分钟,数值(00-59)
  %j
  年的天 (001-366)
  %k
  小时 (0-23)
  %l
  小时 (1-12)
  %M
  月名
  %m
  月,数值(00-12)
  %p
  AM 或 PM
  %r
  时间,12-小时(hh:mm:ss AM 或 PM)
  %S
  秒(00-59)
  %s
  秒(00-59)
  %T
  时间, 24-小时 (hh:mm:ss)
  %U
  周 (00-53) 星期日是一周的第一天
  %u
  周 (00-53) 星期一是一周的第一天
  %V
   (01-53) 星期日是一周的第一天,与 %X使用
  %v
   (01-53) 星期一是一周的第一天,与 %x使用
  %W
  星期名
  %w
  周的天 (0=星期日, 6=星期六)
  %X
  年,其中的星期日是周的第一天,4 位,与 %V使用
  %x
  年,其中的星期一是周的第一天,4 位,与 %v使用
  %Y
  年,4
  %y
  年,2 位
  
  Mysql中还有另外几种返回日期的函数,如:
  SELECT EXTRACT(YEAR_MONTH FROM datecolum ) 返回格式如200902
  EXTRACT() 函数用于返回日期/时间的单独部分,比如年、月、日、小时、分钟等等。
  语法
  EXTRACT(unit FROM date)

  date 参数是合法的日期表达式。unit 参数可以是下列的值:
  
  Unit 值
  MICROSECOND
  SECOND
  MINUTE
  HOUR
  DAY
  WEEK
  MONTH
  QUARTER
  YEAR
  SECOND_MICROSECOND
  MINUTE_MICROSECOND
  MINUTE_SECOND
  HOUR_MICROSECOND
  HOUR_SECOND
  HOUR_MINUTE
  DAY_MICROSECOND
  DAY_SECOND
  DAY_MINUTE
  DAY_HOUR
  YEAR_MONTH
  
  Unit 值
  MICROSECOND
  SECOND
  MINUTE
  HOUR
  DAY
  WEEK
  MONTH
  QUARTER
  YEAR
  SECOND_MICROSECOND
  MINUTE_MICROSECOND
  MINUTE_SECOND
  HOUR_MICROSECOND
  HOUR_SECOND
  HOUR_MINUTE
  DAY_MICROSECOND
  DAY_SECOND
  DAY_MINUTE
  DAY_HOUR
  YEAR_MONTH
  
  检查了一下,大致没有问题,然后又开始寻找如何按月统计,然后就看Date_format的语法,
  %m表示数值,%M表示名称,看后很兴奋的试一下:
  select distinct DATE_FORMAT(check_date ,'%X-%m') c1,avg(weight)/10000 wei from ho_body where user_id=295
and weight >0 and check_date between '2009-02-24' and '2009-10-31' group by c1
  ——————————————————————————————————————
  c1 wei
  2009-08 80.66388889
2009-09 79.70555556
2009-10 78.83714286
  
  然后测试这样计算的结果是否正确,经过测试,果然是没问题的,很有成就感。然后就用这个方法统计,拿取数据,然后将这些统计的结果作为数据集,用JfreeChart画图。后期测试时,发现画的统计图横轴日期有问题,时间范围为2009-02-24~2010-02-24时,图片中竟然多出一个2009年1月,并且在最右侧。我确信我是经过排序的,不可能2009年1月会在最右侧,之后再调试,竟然发现数据库中根本就没有09年1月的数据,更直观的错误是,以between '2009-02-24' and '2009-10-31'条件,根本不可能出现2009-01。
  
  然后将错误原因定位在sql语句上,执行这个语句,果然,原因就在这里:
  select distinct DATE_FORMAT(check_date ,'%X-%m') c1,avg(weight)/10000 wei from ho_body where user_id=295
and weight >0 and check_date between '2009-02-24' and '2010-02-24' group by c1
  ————————————————————————————————————————
  c1 wei
  2009-01 79.8
2009-08 80.66388889
2009-09 79.70555556
2009-10 78.83714286
2009-11 77.64285714
2009-12 78.75
2010-01 79.2
  这个09年1月到底是哪里出来的,我先确定2009年1月是否有数据,结果测试最早的数据为2009-08-01,并没有1月的任何数据。既然最早的数据是8月,那么就测试这个多出来的2009-01是从哪里冒出来的。
  我就用最笨的方法测试:
select distinct DATE_FORMAT(check_date ,'%X-%m')c1 from ho_body where user_id=295 and check_date between '2009-08-01' and '2009-08-31' order by c1
  ————————————————————————————————————————
  c1
  2009-08
  问题不在8月。继续测试:
  select distinct DATE_FORMAT(check_date ,'%X-%m')c1 from ho_body where user_id=295 and check_date between '2009-9-01' and '2009-09-30' order by c1
  ——————————————————————————————————————
  
  c1
  2009-09
  
  ……
  ……
  直到2010年时,
  
select distinct DATE_FORMAT(check_date ,'%X-%m')c1 from ho_body where user_id=295 and check_date between '2010-01-01' and '2010-01-31' order by c1
  ————————————————————————————————————————
  c1
  2009-01
2010-01
  问题就是2010年1月,并且,如果将条件改为between '2010-01-02' and '2010-01-31' 则不会多出2009-01。难道是Date_format函数有bug,在跨年时没有考虑正确,将2010年1月1日归为2009年的1月中?当然我也有怀疑过是我的sql语句有问题,仔细再看了看Date_format()的语法,
  %X表示年,周日为一周第一天
  %x表示年,周一为一周第一天
  %M表示月,名称
  %m表示月,数值,01形式
  %V表示周,周日为第一天
  %v表示周,周一为第一天
  ...........
  
  看来看去,感觉没什么错误呀,感觉自己对这个研究的够清楚明白了,一定没有问题的。
  mysql有bug的想法我坚持了一下午,在我和一个同事说这个bug的时候,老大听到了,问我具体怎么回事,我就给她讲解,特别奇怪的地方在于数据库根本没有09年1月的数据,用mysql中的Date_format的按月统计函数时,在跨年时有问题。老大也觉得这个问题不可思议,这时那个同事说,你怎么用X表示年呀,一般不都是有Y表示年吗?我还反驳说,这个没区别的呀,都是一样的,表示年嘛,4位的。。。。
  后来和他争论之中,为了表明修改这个X,Y什么的没效果,我就改成了%Y-%m,结果却是2009-01没有了!!!!
  怎么会这样????也太低级了吧,之前一直怀疑mysql的bug,竟然是这个原因?然后再仔细看Date_format()的语法,看后快晕过去了,这么低级的错误我怎么之前一直没有发现呢?
  
  
  %M
  月名
  %m
  月,数值(00-1
转自:http://blog.csdn.net/wcp88888888/article/details/6178812  http://blog.csdn.net/wgllz/article/details/5334764

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-290070-1-1.html 上篇帖子: struts2,hibernate,spring三大框架整合的注册程序(xml 配置,mysql数据库) 下篇帖子: 不用复杂配置的超酷软件包-包含 MySQL、PHP 和 Perl 的 Apache 发行版
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表