Es muy similar a Obtenga la primera y la última fecha del próximo mes en MySQL, pero quiero obtener la fecha del primer y último día laborable de algún mes en MySQL. Aquí, día laborable significa simplemente lunes ~ viernes, o DAYOFWEEK (fecha) & gt; = 2 y & lt; = 6. No pensemos en vacaciones.

Por ejemplo (elegí febrero porque debería ser más complicado debido al salto)

2014-02 -> 2014-02-03 (Mon) ~ 2014-02-28 (Fri)
2015-02 -> 2015-02-02 (Mon) ~ 2015-02-27 (Fri)
2016-02 -> 2016-02-01 (Mon) ~ 2016-02-29 (Mon)
1
xosp7tom 28 ene. 2016 a las 03:10

3 respuestas

La mejor respuesta

P.ej.:

SELECT MIN(dt),MAX(dt) FROM calendar WHERE DAYOFWEEK (dt) NOT IN(1,7) AND dt BETWEEN '2016-01-01' AND '2016-01-31';
1
Strawberry 28 ene. 2016 a las 01:32

Feed day1 con el primer día de cualquier mes:

SELECT
if (
    (@w1 := dayofweek(@day1 := '2016-05-01')) = 1,
    adddate(@day1, interval 1 day), 
    if(@w1 = 7, adddate(@day1, interval 2 day), @day1)
) day_one,
if (
    (@w2 := dayofweek(@day2 := last_day(@day1))) = 1,
    adddate(@day2, interval -2 day), 
    if(@w2 = 7, adddate(@day2,interval -1 day), @day2)
) day_last

Breve explicacion:

  1. Si el primer día es domingo, agregue un día
  2. Si el primer día es sábado, agregue dos días

Dar cualquier día de un mes y obtener el último día del mes,

  1. Si el último día es domingo, menos dos días
  2. Si el último día es sábado, menos un día
-1
SIDU 28 ene. 2016 a las 00:37

Aquí hay un pseudocódigo para empezar a pensar en el problema. Para el inicio (final) del mes, busque un día de la semana y avance (retroceda) un día si no. Repita la prueba y posiblemente salte hacia adelante (hacia atrás) nuevamente. Nunca tendrás que moverte más de dos veces.

/* <som> = start of month */
case
    when not (dayofweek(<som>) between 2 and 6)
    then
        case
            when not (dayofweek(<som> + 1) between 2 and 6)
            then <som> + 2
            else <som> + 1
        end
    else <som>
end

/* <eom> = end of month */
case
    when not (dayofweek(<eom>) between 2 and 6)
    then
        case
            when not (dayofweek(<eom> - 1) between 2 and 6)
            then <eom> - 2
            else <eom> - 1
        end
    else <eom>
end

No soy una autoridad de MySQL, pero creo que puedes usar estas sustituciones:

<som> -> date_sub(<dt>, interval dayofmonth(<dt>) - 1 day)
<eom> => last_day(<dt>)

Hay diferentes formas de reescribir esto que son equivalentes. El enfoque anterior fue probablemente la forma en que muchos pensarían inicialmente sobre el problema, pero en realidad es más simple que eso. Dado que una vez que sé en qué día de fin de semana cae una fecha, también sé cuántos días faltan para el siguiente (anterior) día de la semana. Esto se puede manejar como tres casos sencillos:

case dayofweek(<som>)
    when 7 then <som> + 2
    when 1 then <som> + 1
    else <som>
end

case dayofweek(<eom>)
    when 7 then <eom> - 1
    when 1 then <eom> - 2
    else <eom>
end
0
shawnt00 29 ene. 2016 a las 16:03