Oracle SQL中的日期计算

时间:2016-06-21 16:22:35

标签: sql oracle

我在Oracle SQL中有一个非常基本的问题注册日期计算。

我一直在使用以下逻辑来计算年龄并识别年龄> gt = 75的记录:

(Date1 - Date2) / 365.25 >= 75

然而,上述逻辑是针对以下情况错误地计算年龄:

Date1 = MM-DD-2016
Date2 = MM-DD-1947

虽然这里的年龄是69岁,但它出现在我的输出中。在我为两个日期添加to_date之后,查询没有带来此记录。

我的问题是:我之前没有在这个查询中使用过to_date并且正在为其他记录工作,但是为什么它在这种情况下失败了呢?

编辑:我想添加,在输入部分日期时,我的数据库记录值如下所示: Date1是19/6/1547 Date2是2016年6月15日

2 个答案:

答案 0 :(得分:1)

使用add_months()功能:

where date1 >= add_months(date2, 75*12)

几个月的计算比基于天的计算更精确。

或者,您可以使用interval

where date1 >= date2 + interval '75' year

答案 1 :(得分:0)

我能看到你的唯一方法就是如果你的日期存储为-1947而不是1947:

with t (Date1, Date2) as (
  select date '2016-06-15', add_months(date '2016-06-15', -12*level)
  from dual
  connect by level <= 80
  union all
  select date '2016-06-15', date '-1947-06-15'
  from dual
)
select * from t
where (Date1 - Date2) / 365.25 >= 75;

DATE1      DATE2    
---------- ----------
06/15/2016 06/15/1941
06/15/2016 06/15/1940
06/15/2016 06/15/1939
06/15/2016 06/15/1938
06/15/2016 06/15/1937
06/15/2016 06/15/1936
06/15/2016 06/15/1947

最后一张唱片看起来不应该存在。但我的NLS_DATE_FORMAT面具是MM / DD / YYYY(以匹配你所看到的);如果我让它显示年份的标志更有意义:

alter session set nls_date_format = 'MM/DD/SYYYY';

with t (Date1, Date2) as (
  select date '2016-06-15', add_months(date '2016-06-15', -12*level)
  from dual
  connect by level <= 80
  union all
  select date '2016-06-15', date '-1947-06-15'
  from dual
)
select * from t
where (Date1 - Date2) / 365.25 >= 75;

DATE1         DATE2       
------------- -------------
6/15/ 2016    6/15/ 1941   
6/15/ 2016    6/15/ 1940   
6/15/ 2016    6/15/ 1939   
6/15/ 2016    6/15/ 1938   
6/15/ 2016    6/15/ 1937   
6/15/ 2016    6/15/ 1936   
6/15/ 2016    6/15/-1947   

甚至更好:

with t (Date1, Date2) as (
  select date '2016-06-15', add_months(date '2016-06-15', -12*level)
  from dual
  connect by level <= 80
  union all
  select date '2016-06-15', date '-1947-06-15'
  from dual
)
select to_char(date1, 'SYYYY-MM-DD') as date1, to_char(date2, 'SYYYY-MM-DD') as date2
from t
where (Date1 - Date2) / 365.25 >= 75;

DATE1       DATE2     
----------- -----------
 2016-06-15  1941-06-15
 2016-06-15  1940-06-15
 2016-06-15  1939-06-15
 2016-06-15  1938-06-15
 2016-06-15  1937-06-15
 2016-06-15  1936-06-15
 2016-06-15 -1947-06-15

所以你可以看到-1947的日期显示,但是1947年的日期不是。这是超过75年前的事情:

select months_between(date '2016-06-15', date '-1947-06-15')/12 as years from dual;

     YEARS
----------
      3963

在您的值周围添加to_date()的原因是停止显示的记录是您将隐式地将日期转换为字符串,然后使用相同的MM/DD/YYYY格式掩码将其转换回日期。中间字符串包含减号,因此date '-1947-06-15'将成为字符串06/15/1947。当它转换回日期时,符号仍然缺失,字符串06/15/1947变为date '1947-06-15'。现在只有69年前,而不是3963年前。