2012-03-16 22 views
5

Necesito programar algunos artículos en una consulta postgres basada en una fecha de entrega solicitada para un pedido. Por ejemplo, el pedido tiene una entrega solicitada un lunes (20120319, por ejemplo) y el pedido debe prepararse el día laborable anterior (20120316).Calcular el día laborable más cercano en Postgres

¿Pensamientos sobre el método más directo? Estoy abierto a agregar una tabla de fechas. Estoy pensando que debe haber una mejor manera que un largo conjunto de declaraciones de casos usando: SELECCIONE EL EXTRACTO (DOW FROM TIMESTAMP '2001-02-16 20:38:40');

Respuesta

7

Para que la anterior jornada de trabajo:

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

Si desea que el próximo día de trabajo acaba de invertir la consulta.

+0

¿Qué pasa si el viernes es feriado? –

+1

Funcionó como un amuleto. Gracias. Para aclarar una cosa para otros, cuando Clodoaldo dice "invierta la consulta", cámbiela a "seleccionar min (s.a)", no cambie < to >. – Dustin

+0

Vacaciones Voy a manejarlo de forma ligeramente diferente. Supongo que para usar su solución anterior, tendrías que guardarla en alguna parte. Pero son lo suficientemente infrecuentes para nosotros que solo volveremos a programar los pedidos. – 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; 

Es posible que desee cambiar el nombre de algunos de los identificadores :-).

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; 
  • Debería ser más rápido para generar solamente tantos días como sea necesario. Genero una semana antes de la entrega. Eso debería abarcar todas las posibilidades.

  • isodow as extract parameter es más conveniente que dow para probar días laborables.

  • min()/max(), ORDER BY/LIMIT 1, eso es una cuestión de gusto con las pocas filas en mi consulta.

  • Para obtener varios días candidatos en orden descendente, no solo la primera opción, cambie LIMIT 1.

  • Puse el dday (día de entrega) en una subconsulta, por lo que solo debe ingresarlo una vez. Puede ingresar cualquier literal date o timestamp. Se envía a date de cualquier manera.

4

Esto le concede el día hábil anterior.

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 
Cuestiones relacionadas