【问题标题】:Getting all entries whose birthday is today in PostgreSQL在 PostgreSQL 中获取今天生日的所有条目
【发布时间】:2020-06-20 16:47:43
【问题描述】:

我有以下查询,我需要实现一个邮件程序,该邮件程序需要发送给今天生日的所有客户。这每天都会发生。现在我需要实现的只是使用 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';

有没有比我上面做的更好的方法来做这个查询?

【问题讨论】:

    标签: php postgresql


    【解决方案1】:

    您可以将 where 子句设置为:

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

    【讨论】:

    • 去年出生的人呢?
    • 显然我需要去睡觉而不是回答关于 SO 的问题。我会编辑。
    • @jordan - 感谢您的努力,但我们的客户都没有 1 天 ;-)
    • 应该是date_part() 而不是datepart()CURRENT_DATE 不是CURRENT_DATE()
    • 呵呵。不过,我仍然认为我的方法更适合 2 月 29 日的人员/合同。 ;-)
    【解决方案2】:

    如果有问题,年龄函数可以让您解决闰年问题:

    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
    

    【讨论】:

      【解决方案3】:
      WHERE date_part('month', cd.birthdate) = '07' AND date_part('day', cd.birthdate) = '20'
      

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

      【讨论】:

      • 谢谢,但出现此错误提示:没有函数与给定的名称和参数类型匹配。您可能需要添加显式类型转换。
      • datepart() 不是 Postgres 函数,应该是 date_part()
      • 是的,我错过了下划线。但是你应该使用@Jordan 解决方案,这是最好的。
      【解决方案4】:

      @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

      【讨论】:

        【解决方案5】:

        试试类似的东西:

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

        【讨论】:

        • 我也想过这个问题——乔丹的回答是好的:)
        • 不,不是……他提取的是年份而不是日期,但这仍然无法解决闰年。我个人会使用 age()(请参阅我的回答)。
        【解决方案6】:

        IMO 的最佳方式是使用to_char(birthday, 'MM-DD') in (?),您只需提供映射到'MM-DD' 的日期范围来代替?。除非您必须支持非常大的日期范围,否则此解决方案非常简单、干净且可抵抗错误。

        【讨论】:

          【解决方案7】:

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

          将愿望细节提取为excel,让wishing app处理一切。

          至少它只需要两件事 excel 文件 以及希望的详细信息(日期、姓名、电子邮件)和一个配置文件(application.properties),仅此而已,你可以走了。

          还有各种options to run 本地应用程序(命令行、前台、后台、docker、windows 调度程序、unix cron 等)云。

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

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

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

          【讨论】:

            猜你喜欢
            • 2017-02-18
            • 2020-09-28
            • 1970-01-01
            • 2021-12-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多