Oracle - 生日日期数学

时间:2014-03-25 23:01:43

标签: sql oracle date-arithmetic

大家好,我这里没有任何代码可以显示,因为我无法用干净的方式来解决这个问题。在我们的表中,我有一个生日列,它是一个时间戳。我需要找到所有在未来3个月内生日的人。

所以我知道我可以在sysdate中添加3个月,但是如何在忽略年份时进行日期比较,我会抛出一个循环。

3 个答案:

答案 0 :(得分:0)

挑战是获得从现在到下一个生日间隔的月数。 MONTHS_BETWEEN()函数加上除以12会使我们接近,但我们必须处理小数尘埃并将余数转换为有用的东西。我可以考虑两种方法来解决这个问题:MOD()CEIL()

使用CEIL我们将在下一个生日和当前年龄之间取差异,并在谓词中使用它。在这种情况下,结果是十进制年份,因此我们需要比较四分之一年(3/12):

where (ceil(months_between(sysdate, b.birthday)/12) - 
      months_between(sysdate, b.birthday)/12) <= 3/12;

这有点笨拙。或者,MOD会给我们剩下几个月的时间,因此从12减去MOD会给我们剩下的时间:

where (12 - mod(months_between(sysdate, b.birthday),12)) <= 3;

这里有样本数据:

with b as 
  (select date '1990-05-10' birthday from dual union all
  select date '1970-09-23' from dual union all
  select date '2000-04-02' from dual union all
  select date '1948-11-12' from dual)
select 
  b.birthday,
  months_between(sysdate, b.birthday) months,
  months_between(sysdate, b.birthday)/12 years,
  ceil(months_between(sysdate, b.birthday)/12) age_to_be,
  ceil(months_between(sysdate, b.birthday)/12) - months_between(sysdate, b.birthday)/12 period_to_birthday,
  mod(months_between(sysdate, b.birthday),12) mod_months,
  12 - mod(months_between(sysdate, b.birthday),12) months_diff
from b
where (12 - mod(months_between(sysdate, b.birthday),12)) <= 3;
-- Or
--where (ceil(months_between(sysdate, b.birthday)/12) - 
--      months_between(sysdate, b.birthday)/12) <= 3/12;

编辑:我会在这里留下我原来错误的答案以供参考,我只是从另一个方向看。

只需使用ADD_MONTHS()LAST_DAY()查找生日在计算值范围内的所有行。无需担心年份组件,您不使用字符串文字。

此示例将sysdate转换为timestamp,然后获取当月的最后一天,并为此添加三个月:

select add_months(last_day(cast(sysdate as timestamp)),3) from dual;

因此,使用该逻辑,您可以:

select *
from your_table
where birthday <= add_months(last_day(cast(sysdate as timestamp)),3);

或者只是:

select *
from your_table
where birthday <= add_months(last_day(sysdate),3);

Oracle很好地为您处理数据类型转换。

答案 1 :(得分:0)

逻辑有点复杂,因为年终包装。但这应该有效:

where (extract(month from sysdate) < 10 and
       to_char(birthday, 'MM-DD') between to_char(sysdate, 'MM-DD') and
                                          to_char(add_month(sysdate, 3), 'MM-DD')
       ) or
       (extract(month from sysdate) >= 10 and
        (to_char(birthday, 'MM-DD') >= to_char(sysdate, 'MM-DD')  or
         to_char(birthday, 'MM-DD') <= to_char(add_month(sysdate, 3), 'MM-DD')
        )
       );

答案 2 :(得分:0)

一个人在当年的生日(周年纪念日),如果他们的出生日期是:

TRUNC(SYSDATE,'Y') + (dob - TRUNC(dob,'Y'))

您可以通过以下方式判断这是否在接下来的三个月内:

SELECT 'Yes' FROM dual
WHERE TRUNC(SYSDATE,'Y') + (dob - TRUNC(dob,'Y'))
BETWEEN SYSDATE AND ADD_MONTHS(SYSDATE,3);

只有一个小问题,就是如果这个人在闰年12月31日出生,这种方法在非闰年运行时会出现一个错误(即它不会确定该人在未来三个月内开始,直至10月1日)。