如果有问题,年龄函数可以让您解决闰年问题:
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);
(请注意,技术上它不是不可变的,因为日期取决于时区。但是创建索引需要不可变的部分,如果您不完全更改时区,它是安全的这个地方。)
编辑:我刚刚对上述内容进行了一些测试,索引建议实际上不适用于 2 月 29 日。 2 月 29 日产生的 day_of_birth 为 1 星期一 28 天,虽然正确,但需要将其添加到 Jan-1st 才能产生当年的有效出生日期。
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