我在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日
答案 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年前。