2011-07-20 52 views
5

我有以下查詢,我需要實現一個需要發送給今天生日的所有客戶端的郵件程序,這是每天發生的事情,現在我需要實現只是使用Postgres SQL查詢來選擇生日客戶端,而不是使用PHP進行過濾。今天在PostgreSQL中獲取所有生日的條目

存儲在數據庫中的日期格式爲YYYY-MM-DD,例如。 1984年3月13日

我所擁有的是下面的查詢

SELECT cd.firstname, 
     cd.surname, 
     SUBSTRING(cd.birthdate,6), 
     cd.email 
FROM client_contacts AS cd 
    JOIN clients AS c ON c.id = cd.client_id 
WHERE SUBSTRING(birthdate,6) = '07-20'; 

是否有更好的方法來做到這一點查詢比我上面做?

回答

8

你可以設置你的where子句:

WHERE 
    DATE_PART('day', birthdate) = date_part('day', CURRENT_DATE) 
AND 
    DATE_PART('month', birthdate) = date_part('month', CURRENT_DATE) 
+0

那去年生的人呢? –

+2

顯然我需要睡覺,而不是回答這個問題。我會編輯。 – Jordan

+0

@jordan - 感謝您的努力,但我們的客戶沒有一天是老;-) – Roland

-1

的東西,如嘗試:

WHERE EXTRACT(DOY FROM TIMESTAMP cd.birthdate) = EXTRACT(DOY FROM TIMESTAMP CURRENT_TIMESTAMP) 
+0

這對閏年來說沒有好處。 –

+0

我也這麼想過 - 喬丹的答案是那麼好:) –

+0

不,這不是......他在提取年份而不是一天,而這仍然不會解決閏年。我會親自使用age()(請參閱我的答案)。 –

0
WHERE date_part('month', cd.birthdate) = '07' AND date_part('day', cd.birthdate) = '20' 

你可以閱讀更多有關此here

+0

Thx,但出現此錯誤提示:沒有函數與給定的名稱和參數類型匹配。您可能需要添加明確的類型轉換。 – Roland

+2

datepart()不是Postgres函數,它應該是date_part() –

+0

是的,我錯過了下劃線。但是你應該使用@Jordan解決方案,這是最好的。 –

5

如果它的事項,年齡功能將讓您解決閏年問題:

where age(cd.birthdate) - (extract(year from age(cd.birthdate)) || ' years')::interval = '0'::interval 

如果你想要表現,你可以用任意的起點(例如, 'epoch'::date)到一個函數,也和它使用索引:

create or replace function day_of_birth(date) 
    returns interval 
as $$ 
    select age($1, 'epoch'::date) 
     - (extract(year from age($1, 'epoch'::date)) || ' years')::interval; 
$$ language sql immutable strict; 

create index on client_contacts(day_of_birth(birthdate)); 

... 

where day_of_birth(cd.birthdate) = day_of_birth(current_date); 

(請注意,這不是技術上一成不變的,因爲日期取決於時區,但需要不可改變的部分來創建索引,它是安全的,如果你不更改時區所有的地方)


編輯:我剛剛測試了一下上方,該指數的建議其實並不二月至29日工作。 2月29日產生1天28天的日期,雖然正確,但需要在1月1日之前添加,以產生當年的有效出生日期。

create or replace function birthdate(date) 
    returns date 
as $$ 
    select (date_trunc('year', now()::date) 
     + age($1, 'epoch'::date) 
     - (extract(year from age($1, 'epoch'::date)) || ' years')::interval 
     )::date; 
$$ language sql stable strict; 

with dates as (
    select d 
    from unnest('{ 
    2004-02-28,2004-02-29,2004-03-01, 
    2005-02-28,2005-03-01 
    }'::date[]) d 
) 
select d, 
     day_of_birth(d), 
     birthdate(d) 
from dates; 

    d  | day_of_birth | birthdate 
------------+---------------+------------ 
2004-02-28 | 1 mon 27 days | 2011-02-28 
2004-02-29 | 1 mon 28 days | 2011-03-01 
2004-03-01 | 2 mons  | 2011-03-01 
2005-02-28 | 1 mon 27 days | 2011-02-28 
2005-03-01 | 2 mons  | 2011-03-01 
(5 rows) 

而且這樣的:

where birthdate(cd.birthdate) = current_date 
-1

最好的辦法海事組織使用to_char(birthday, 'MM-DD') in (?),你只需要給代替?映射到'MM-DD'一些日期範圍。除非你必須支持非常大的日期範圍,否則這個解決方案非常簡單,乾淨並且有缺陷。

相關問題