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

r55awzrz  于 2023-08-02  发布在  PHP
关注(0)|答案(8)|浏览(98)

我有下面的查询,我需要实现一个Mailer,需要发送给所有的客户谁的生日是今天。这种情况每天都会发生。现在我需要实现的只是使用Postgres SQL查询选择生日客户端,而不是在PHP中过滤它们。
数据库中存储的日期格式为YYYY-MM-DD,例如:1984-03-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';

字符串
有没有比我上面做的更好的方法来完成这个查询?

jgwigjjp

jgwigjjp1#

你可以将where子句设置为:

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

字符串

kd3sttzy

kd3sttzy2#

如果有问题,age函数可以让你解决闰年的问题:

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

字符串
如果你想要性能,你实际上可以用一个任意的起点来 Package 上面的内容(例如:'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);


(Note它不是“技术上”不变的,因为日期取决于时区。但是创建索引需要不可变的部分,如果您不到处更改时区,这是安全的。)
编辑:我刚刚测试了上面的一点,指数建议实际上在2月29日不起作用。Feb-29 th产生的出生日为1 mon 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

zbq4xfa0

zbq4xfa03#

@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

kcrjzv8t

kcrjzv8t4#

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

字符串
你可以阅读更多关于这个here

wr98u20j

wr98u20j5#

WHERE 0 = extract(DAY FROM age(dob)) + extract (MONTH FROM age(dob))

字符串

uujelgoq

uujelgoq6#

尝试类似这样的东西:

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

字符串

f45qwnt8

f45qwnt87#

IMO最好的方法是使用to_char(birthday, 'MM-DD') in (?),你只给予一些Map到'MM-DD'的日期范围来代替?。除非你必须支持非常大的日期范围,否则这个解决方案非常简单,干净和防bug。

tzcvj98z

tzcvj98z8#

您尝试做的是,提取使用SQL手动希望的人员详细信息,并单独手动发送愿望。如果我建议你一个更好的方法呢?
将愿望细节提取为excel,让wishing app处理一切。
最少它只需要两个东西excel文件与愿望详细信息(日期,姓名,电子邮件)和配置文件(application.properties),这就是它,你是好去。
此外,还有各种options to run本地应用程序(命令行,前台,后台,docker,windows调度程序,unix cron等)云。
应用程序为highly configurable,您可以配置各种细节,如:

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

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

相关问题