sql >> Base de Datos >  >> RDS >> Oracle

¿Cuál es la alternativa de MySQL a la función NEXT_DAY de Oracle?

Voy a tirar mi sombrero en el ring con otro enfoque:

Editar: Me doy cuenta con cierto retraso de que la función de Oracle en cuestión toma una cadena como segundo argumento, por lo que no se ajusta con precisión al requisito. Sin embargo, MySQL ya ha definido amablemente 0 - 6 como lunes - domingo, y de todos modos tengo objeciones morales al uso de una cadena como argumento para este tipo de cosas. Una cadena vendría de la entrada del usuario o otra asignación más en código de nivel superior entre valores numéricos y de cadena. ¿Por qué no pasar un número entero? :)

CREATE FUNCTION `fnDayOfWeekGetNext`(
        p_date DATE,
        p_weekday TINYINT(3)
        ) RETURNS date
BEGIN

        RETURN DATE_ADD(p_date, INTERVAL p_weekday - WEEKDAY(p_date) + (ROUND(WEEKDAY(p_date) / (p_weekday + WEEKDAY(p_date) + 1)) * 7) DAY);

END

Para desglosar la parte que determina el INTERVAL valor:

La primera parte de la ecuación simplemente obtiene el desplazamiento entre el día de la semana especificado y el día de la semana de la fecha especificada:

p_weekday - WEEKDAY(p_date)

Esto devolverá un número positivo si p_weekday es mayor que WEEKDAY(p_date) y viceversa. Se devolverá cero si son iguales.

El ROUND() segmento se utiliza para determinar si el día de la semana solicitado (p_weekday ) ya ha ocurrido en la semana actual en relación con la fecha (p_date ) especificado. Entonces, por ejemplo...

ROUND(WEEKDAY('2019-01-25') / (6 + WEEKDAY('2019-01-25') + 1))

..devuelve 0 , indicando que el domingo (6 ) no ha ocurrido esta semana, ya que 2019-01-25 es un viernes Del mismo modo...

ROUND(WEEKDAY('2019-01-25') / (2 + WEEKDAY('2019-01-25') + 1))

...devuelve 1 porque el miércoles (2 ) ya ha pasado. Tenga en cuenta que esto devolverá 0 si p_weekday es el mismo que el día de la semana de p_date .

Este valor (ya sea 1 o 0 ) luego se multiplica por la constante 7 (el número de días en una semana).

Por lo tanto, si p_weekday ya ha ocurrido en la semana actual, agregará 7 al desplazamiento p_weekday - WEEKDAY(p_date) , porque ese desplazamiento sería un número negativo y queremos una fecha en el futuro.

Si p_weekday aún no ha ocurrido en la semana actual, entonces podemos agregar el desplazamiento a la fecha actual porque el desplazamiento será un número positivo. De ahí la sección ROUND(...) * 7 es igual a cero y, en esencia, ignorado.

Mi deseo para este enfoque era simular un IF() condición matemática. Esto sería igualmente válido:

RETURN DATE_ADD(p_date, INTERVAL p_weekday - WEEKDAY(p_date) + IF(p_weekday - WEEKDAY(p_date) < 0, 7, 0) DAY);

Y en aras de la objetividad, al ejecutar 1 millón de iteraciones varias veces de cada función, el IF -la versión basada en promedio fue un 4,2 % más rápida que la ROUND -versión basada.