【问题标题】:Calculate closest working day in Postgres计算 Postgres 中最近的工作日
【发布时间】:2012-03-16 20:04:49
【问题描述】:

我需要根据订单的请求交货日期在 postgres 查询中安排一些项目。例如,订单要求在星期一发货(例如 20120319),订单需要在前一个工作日准备好(20120316)。

想到最直接的方法?我愿意添加日期表。我认为必须有比使用一长串案例陈述更好的方法: SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');

【问题讨论】:

    标签: sql postgresql date


    【解决方案1】:

    这会让您获得前一个工作日。

    SELECT 
        CASE (EXTRACT(ISODOW FROM current_date)::integer) % 7
            WHEN 1 THEN current_date-3
            WHEN 0 THEN current_date-2
            ELSE current_date-1
        END AS previous_business_day
    

    【讨论】:

      【解决方案2】:

      有前一个工作日:

      select max(s.a) as work_day
      from (
          select s.a::date
          from generate_series('2012-01-02'::date, '2050-12-31', '1 day') s(a)
          where extract(dow from s.a) between 1 and 5
          except
          select holiday_date
          from holiday_table
          ) s
      where s.a < '2012-03-19'
      ;
      

      如果您想要下一个工作日,只需反转查询即可。

      【讨论】:

      • 如果星期五是假期怎么办?
      • 工作就像一个魅力。谢谢。为了向其他人澄清一件事,当 Clodoaldo 说“反转查询”时,将其更改为“select min(s.a)”,而不是将 。
      • 假期我将稍微不同地处理。我假设使用他上面的解决方案,你必须将它们存储在某个地方。但它们对我们来说很少见,我们只会重新安排订单。
      • @Dustin 要反转,您应该同时执行 min&gt;
      • 我在 Postgres 中是否有一个 holiday_table 丢失了?
      【解决方案3】:
      SELECT y.d AS prep_day
      FROM  (
          SELECT generate_series(dday - 8, dday - 1, interval '1d')::date AS d
          FROM (SELECT '2012-03-19'::date AS dday) x
          ) y
      LEFT   JOIN holiday h USING (d)
      WHERE  h.d IS NULL
      AND    extract(isodow from y.d) < 6
      ORDER  BY y.d DESC
      LIMIT  1;
      
      • 生成所需天数应该更快。我在交货前一周生成。这应该涵盖所有可能性。

      • isodow as extract parameterdow 更方便测试工作日。

      • min() / max(), ORDER BY / LIMIT 1,这是我查询中的几行的口味问题。

      • 要按降序排列候选天数,而不仅仅是首选天数,请更改LIMIT 1

      • 我将dday(交货日期)放在子查询中,因此您只需输入一次。您可以输入任何 datetimestamp 文字。无论哪种方式,它都会转换为date

      【讨论】:

        【解决方案4】:
        CREATE TABLE Holidays (Holiday, PrecedingBusinessDay) AS VALUES
          ('2012-12-25'::DATE, '2012-12-24'::DATE),
          ('2012-12-26'::DATE, '2012-12-24'::DATE);
        SELECT Day, COALESCE(PrecedingBusinessDay, PrecedingMondayToFriday)
        FROM
          (SELECT Day, Day - CASE DATE_PART('DOW', Day)
                                 WHEN 0 THEN 2
                                 WHEN 1 THEN 3
                                 ELSE 1
                             END AS PrecedingMondayToFriday
           FROM TestDays) AS PrecedingMondaysToFridays
        LEFT JOIN Holidays ON PrecedingMondayToFriday = Holiday;
        

        您可能想要重命名一些标识符:-)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-17
          • 2010-09-25
          • 1970-01-01
          • 2011-01-14
          • 1970-01-01
          相关资源
          最近更新 更多