2014-03-25 122 views
2

大家好,我沒有代碼在這裏顯示,因爲我無法用乾淨的方式來包裝我的頭。在我們的表格中,我有一個生日專欄,它是一個時間戳。我需要找到在未來3個月內生日的所有人。甲骨文 - 生日日期數學

所以我知道我可以添加3個月的sysdate,但我怎麼做日期比較,而忽略了一年我有一個循環引發。

回答

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()查找生日在計算值內的所有行。無需擔心年份組件,您不使用字符串文字。

這個例子蒙上sysdatetimestamp,則得到當月的最後一天,並增加了三個月,即:

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很好地處理數據類型轉換rsion爲你。

+1

這使得OP在談論出生日期的假設 - 而我很確定他們是指生日,即某人出生的週年紀念日。這個邏輯會說我的生日已經過去了 - 但在9月份我很確定我的妻子會烘烤我的生日蛋糕:) –

+0

@JeffreyKemp Zoink!你是對的。我花了一些時間在面對現實之前。我用另一種解決方案更新了答案。感謝您的解釋。 – Wolf

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') 
     ) 
     ); 
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日)。