Рассчитать ближайший рабочий день в Postgres - PullRequest
6 голосов
/ 17 марта 2012

Мне нужно запланировать некоторые позиции в запросе postgres на основе запрошенной даты доставки заказа. Так, например, заказ имеет запрошенную доставку в понедельник (например, 20120319), и заказ должен быть подготовлен в предыдущий рабочий день (20120316).

Мысли о самом прямом методе? Я открыт для добавления таблицы дат. Я думаю, что должен быть лучший способ, чем длинный набор инструкций case: ВЫБРАТЬ ЭКСТРАКТ (DOW FRIM TIMESTAMP '2001-02-16 20:38:40');

Ответы [ 4 ]

7 голосов
/ 14 апреля 2014

Это даст вам предыдущий рабочий день.

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
7 голосов
/ 17 марта 2012

Чтобы иметь предыдущий рабочий день:

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'
;

Если вы хотите следующий рабочий день, просто инвертируйте запрос.

4 голосов
/ 17 марта 2012
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, поскольку параметр извлечения удобнее, чем dow, для проверки на рабочие дни.

  • min() / max(), ORDER BY / LIMIT 1, это вопрос вкуса с несколькими строками в моем запросе.

  • Чтобы получить несколько дней кандидатов в порядке убывания,измените LIMIT 1.

  • Я поместил dday (день доставки) в подзапрос, так что вы должны ввести его только один раз.Вы можете ввести любой date или timestamp литерал.Он кастуется в date в любом случае.

0 голосов
/ 17 марта 2012
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;

Возможно, вы захотите переименовать некоторые из идентификаторов: -).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...