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

时间:2011-07-20 08:01:16

标签: 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';

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

6 个答案:

答案 0 :(得分:11)

您可以将where子句设置为:

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

答案 1 :(得分: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);

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


编辑:我刚刚对上面的内容进行了测试,索引建议实际上并不适用于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)

因此:

where birthdate(cd.birthdate) = current_date

答案 2 :(得分:0)

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

您可以阅读有关此here

的更多信息

答案 3 :(得分:0)

@Jordan答案是正确的,但是如果您的日期格式是字符串,它将无法正常工作。如果是字符串,则使用to_date函数对其进行类型转换。然后应用date_part函数。

如果出生日期(DOB)是20/04/1982,那么查询是:

SELECT * FROM public."studentData" where date_part('day',TO_DATE("DOB", 'DD/MM/YYYY'))='20' 
AND date_part('month',TO_DATE("DOB", 'DD/MM/YYYY'))='04';

EXTRACT(MONTH FROM TO_DATE("DOB", 'DD/MM/YYYY'))='04' AND EXTRACT(DAY FROM TO_DATE("DOB", 'DD/MM/YYYY'))='20'

我在表名(" studentData")和字段名称(" DOB")中添加双引号,因为它是字符串。

归功于@Jordan

答案 4 :(得分:-1)

尝试使用以下内容:

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

答案 5 :(得分:-1)

您想要做的是,使用SQL手动提取需要的人的详细信息,然后手动发送希望。如果我建议您采用更好的方法怎么办?

以excel格式提取愿望详细信息,并让wishing app处理所有事情。

它至少需要两件 excel文件,其中包含愿望详细信息(日期,姓名,电子邮件)和配置文件( application.properties ),就是这样,你很好。

此外,本地有各种options to run应用程序(命令行,前台,后台,泊坞窗,Windows Scheduler,Unix cron等)云。

应用程序为highly configurable,您可以配置各种详细信息,例如:

  • 工作簿加载选项
  • 带有愿望的图像选项。
  • SMTP配置
  • 其他应用程序级别的配置,例如何时发送愿望,迟来的愿望,日志记录等。

    免责声明:我是该应用程序的所有者