在PostgreSQL中获取今天生日的所有条目

Rol*_*and 7 php postgresql

我有以下查询,我需要实现一个Mailer,需要发送给今天生日的所有客户.这种情况每天发生.现在我需要实现的只是选择使用Postgres SQL查询的Birthday客户端,而不是在PHP中过滤它们.

存储在数据库中的日期格式是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';
Run Code Online (Sandbox Code Playgroud)

有没有比我上面做的更好的方法来进行此查询?

Jor*_*dan 11

您可以将where子句设置为:

WHERE
    DATE_PART('day', birthdate) = date_part('day', CURRENT_DATE)
AND
    DATE_PART('month', birthdate) = date_part('month', CURRENT_DATE)
Run Code Online (Sandbox Code Playgroud)

  • 应该是`date_part()`而不是`datepart()`和`CURRENT_DATE`而不是`CURRENT_DATE()` (3认同)
  • 显然我需要上床而不是回答问题.我会编辑. (2认同)
  • 呵呵。我仍然认为,对于2月29日签订的人/合同,我的方法更好。;-) (2认同)

Den*_*rdy 5

如果重要,年龄函数将让您解决闰年问题:

where age(cd.birthdate) - (extract(year from age(cd.birthdate)) || ' years')::interval = '0'::interval
Run Code Online (Sandbox Code Playgroud)

如果您想要性能,您实际上可以将上面的任意起点(例如'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);
Run Code Online (Sandbox Code Playgroud)

(请注意,它在技术上是不可变的,因为日期取决于时区.但是创建索引需要不可变部分,如果你没有在整个地方改变时区,那么它是安全的.)


编辑:我刚刚测试了上面的一点,索引建议实际上不适用于feb-29th.2月29日产生1天28天的day_of_birth,虽然正确,但需要添加到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)
Run Code Online (Sandbox Code Playgroud)

因此:

where birthdate(cd.birthdate) = current_date
Run Code Online (Sandbox Code Playgroud)