2012-03-16 25 views
5

Tôi cần lập lịch một số mục trong truy vấn postgres dựa trên ngày giao hàng được yêu cầu cho một đơn đặt hàng. Vì vậy, ví dụ, thứ tự có một giao hàng được yêu cầu vào một thứ hai (ví dụ 20120319), và thứ tự cần phải được chuẩn bị vào ngày làm việc trước đó (20120316).Tính ngày làm việc gần nhất trong Postgres

Suy nghĩ về phương pháp trực tiếp nhất? Tôi đang mở để thêm một bảng ngày tháng. Tôi nghĩ rằng phải có một cách tốt hơn là một tập hợp các câu lệnh trường hợp dài sử dụng: SELECT EXTRACT (DOW FROM TIMESTAMP '2001-02-16 20:38:40');

Trả lời

7

Để có ngày làm việc trước đó:

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

Nếu bạn muốn ngày làm việc tiếp theo chỉ Invert truy vấn.

+0

Điều gì xảy ra nếu ngày thứ sáu là ngày lễ? –

+1

Làm việc như một sự quyến rũ. Cảm ơn. Để làm rõ một điều cho người khác, khi Clodoaldo nói "đảo ngược truy vấn" nó thay đổi nó thành "chọn min (s.a)", không thay đổi < to >. – Dustin

+0

Ngày lễ tôi sẽ xử lý hơi khác nhau. Tôi giả sử sử dụng giải pháp của ông ở trên, bạn phải lưu trữ chúng ở đâu đó. Nhưng chúng không đủ thường xuyên cho chúng tôi để chúng tôi sẽ lên lịch lại các đơn đặt hàng. – Dustin

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

Bạn có thể muốn đổi tên một số số nhận dạng :-).

4
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; 
  • Nó phải là nhanh để tạo ra chỉ như nhiều ngày khi cần thiết. Tôi tạo ra một tuần trước khi giao hàng. Điều đó sẽ bao gồm tất cả các khả năng.

  • isodow as extract parameter thuận tiện hơn dow để kiểm tra ngày làm việc.

  • min()/max(), ORDER BY/LIMIT 1, đó là vấn đề về hương vị với một vài hàng trong truy vấn của tôi.

  • Để nhận được nhiều ngày ứng cử viên theo thứ tự giảm dần, không chỉ là lựa chọn hàng đầu, hãy thay đổi LIMIT 1.

  • Tôi đặt dday (ngày phân phối) trong truy vấn phụ để bạn chỉ phải nhập một lần. Bạn có thể nhập bất kỳ số date hoặc timestamp nào. Nó được đúc thành date một trong hai cách.

4

Điều này mang lại cho bạn ngày làm việc trước đó.

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 
Các vấn đề liên quan