Chinaunix首页 | 论坛 | 博客
  • 博客访问: 723598
  • 博文数量: 94
  • 博客积分: 1937
  • 博客等级: 上尉
  • 技术积分: 1618
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-04 18:46
个人简介

专注数据库开发管理

文章分类

全部博文(94)

文章存档

2015年(1)

2014年(2)

2013年(19)

2012年(32)

2011年(10)

2010年(30)

分类: Oracle

2012-11-30 10:45:21

/* 由大小月份引起的日期计算时值得注意的一个问题 */

SQL> 

SQL> SELECT DATE'2012-10-30' 上月30日, DATE'2012-11-30' 今日,add_months( DATE'2012-10-30',1) 上月增加一月,
  2         add_months( DATE'2012-11-30',-1) 本月减少一月 FROM dual;
 
上月30日    今日        上月增加一月 本月减少一月
----------- ----------- ------------ ------------
2012-10-30  2012-11-30  2012-11-30   2012-10-31

结果表明:10-30加1个月为11-30,而11-30减1个月结果却为10-31,也就是说大月30日增加1个月结果为小月30日,小月减少1个月结果为大月31日。
oracle的日期如此计算应该说是比较合理的,但在开发如计算同比等指标有一点值得注意,看下面的例子:

SQL> SELECT id,pub_date FROM mm;
 
                                     ID PUB_DATE
--------------------------------------- -----------
                                      1 2012-11-30
                                      2 2012-10-31
                                      3 2012-10-30
 
SQL> SELECT m1.pub_date m1date, m2.pub_date m2date ,m1.id/m2.id
  2  FROM mm m1 ,mm m2
  3  WHERE add_months(m2.pub_date,-1)=m1.pub_date;
 
M1DATE      M2DATE      M1.ID/M2.ID
----------- ----------- -----------
2012-10-31  2012-11-30            2

只有一条记录,11-30与10-30比较

SQL> SELECT m1.pub_date m1date, m2.pub_date m2date ,m1.id/m2.id
  2  FROM mm m1 ,mm m2
  3  WHERE add_months(m1.pub_date,1)=m2.pub_date;
 
M1DATE      M2DATE      M1.ID/M2.ID
----------- ----------- -----------
2012-10-30  2012-11-30            3
2012-10-31  2012-11-30            2

生成了两条记录,11-30与10-30、10-31都对应上了,既然大小月份会引起该问题,那么遇到2月平闰月的情况,情况也是类似的。

-- 向表中插入一些测试数据
SQL> SELECT id,pub_date FROM mm;
 
                                     ID PUB_DATE
--------------------------------------- -----------
                                      1 2012-11-30
                                      2 2012-10-31
                                      4 2012-1-28
                                      5 2012-1-29
                                      6 2012-1-30
                                      7 2012-1-31
                                      8 2012-2-28
                                      9 2012-2-29
                                      3 2012-10-30
 
9 rows selected

SQL> 
SQL> SELECT m1.pub_date m1date, m2.pub_date m2date ,m1.id/m2.id
  2  FROM mm m1 ,mm m2
  3  WHERE add_months(m2.pub_date,-1)=m1.pub_date AND m2.id=8;
 
M1DATE      M2DATE      M1.ID/M2.ID
----------- ----------- -----------
2012-1-28   2012-2-28           0.5

SQL> SELECT m1.pub_date m1date, m2.pub_date m2date ,m1.id/m2.id
  2  FROM mm m1 ,mm m2
  3  WHERE add_months(m1.pub_date,1)=m2.pub_date AND m2.id=8;
 
M1DATE      M2DATE      M1.ID/M2.ID
----------- ----------- -----------
2012-1-28   2012-2-28           0.5

日期为2012-2-28日参与计算时均只有一条,不受大小月份的影响,再看29日的情形:

SQL> SELECT m1.pub_date m1date, m2.pub_date m2date ,m1.id/m2.id
  2  FROM mm m1 ,mm m2
  3  WHERE add_months(m2.pub_date,-1)=m1.pub_date AND m2.id=9;
 
M1DATE      M2DATE      M1.ID/M2.ID
----------- ----------- -----------
2012-1-31   2012-2-29   0.777777777

2012-2-29向前推1个月为2012-1-31,也只有1条记录,这与上面测试结果是一致的。

SQL> SELECT m1.pub_date m1date, m2.pub_date m2date ,m1.id/m2.id
  2  FROM mm m1 ,mm m2
  3  WHERE add_months(m1.pub_date,1)=m2.pub_date AND m2.id=9;
 
M1DATE      M2DATE      M1.ID/M2.ID
----------- ----------- -----------
2012-1-29   2012-2-29   0.555555555
2012-1-30   2012-2-29   0.666666666
2012-1-31   2012-2-29   0.777777777

日期2012-1-29向后推1个月则产生了3条记录。

因此,在开发过程中计算月同比等指标时须注意,若非严格要求可采用30天时间差或利用当前日期减少1个月来来消除此现象。
阅读(1267) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~