jueves, 18 de octubre de 2012

Jugando con fechas y semanas en MySQL

Nuevamente, la necesidad lleva a encontrar nuevas opciones (para mi caso, pues quizás lo que he aprendido ya alguien lo ha tenido en sus manos desde hace mucho), y dado que mi problema no encontró solución en San Google, creo que lo mejor es compartirlo, por si alguien más se topa con una situación como por la que he pasado: Un determinado proyecto ha solicitado un "aplicativo" en PHP que genere un reporte con varias condiciones, pero dos que en particular han generado algunos inconvenientes:


  • Se necesita generar el reporte por semana del año (indicando claro el rango de fechas de la semana)
  • Se necesita generar el reporte para un rango de fechas específico, pero en el resultado se debe indicar el numero de semana para cada fecha que este dentro del rango.

Muchos quizás dirán que es algo muy trivial o incluso ya existirá una función en PHP que lo hace todo, pero como dije para mi no lo fue, no dí con algo que me solucionara el problema rápidamente, y como estaba trabajando con MySQL, traté de hallar una solución con la base de datos, la cual encontré en estas dos consultas:


SELECT WEEKOFYEAR('2012-10-14') as Semana
(WEEKDAY('2012-10-14')+1) as DiaSemana,
DAYOFYEAR('2012-10-14') as DiaAnno
DAYNAME('2012-10-14') as NombreDia,
TIMESTAMPADD(DAY,(0-WEEKDAY('2012-10-14')),'2012-10-14') as PrimerDiaSemana,  
TIMESTAMPADD(DAY,(6-WEEKDAY('2012-10-14')),'2012-10-14') as UltimoDiaSemana

SELECT MAKEDATE(YEAR(NOW()),(1*7)),
TIMESTAMPADD(DAY,(0-WEEKDAY(MAKEDATE(YEAR(NOW()),(1*7)))), 
MAKEDATE(YEAR(NOW()),(1*7))) as PrimerDiaSemana,  
TIMESTAMPADD(DAY,(6-WEEKDAY(MAKEDATE(YEAR(NOW()),(1*7)))), 
MAKEDATE(YEAR(NOW()),(1*7))) as UltimoDiaSemana  

Como se puede apreciar es un tema simple conociendo las funciones adecuadas; a continuación detallo cada acción para la consulta 1 que recibe una fecha:

  • Weekofyear('2012-10-14'): en base a la fecha retorna la semana a la que pertenece.
  • Weekday('2012-10-14'): Retorna el día de la semana para esa fecha en partícular (0 es lunes, por eso sumo 1 para hacer una correspondencia más cercana a lo que se usa normalmente).
  • Dayofyear('2012-10-14'):  Retorna el numero del día en el año (entre 1 y 365) para la fecha indicada.
  • DayName('2012-10-14'): Retorna el nombre del día para la fecha indicada (Lunes, martes, miércoles.....   ).
  • Timestampadd(...): Esta función suma un numero determinado (segundo parámetro)de días, meses o lo que se defina en el primer parámetro a una fecha determinada (tercer parámetro). Como la idea es conseguir el primer y último día de la semana en el segundo parámetro se juega con la diferencia entre el día de la semana (Weekday) y el numero de días de la semana (entre 0 y 6), el numero positivo o negativo nos dará el día inicial o el final.
La segunda consulta recibe el numero de semana y entrega el primer y último día haciendo uso de la misma función de la consulta anterior (Timestampadd) pero agregando algo:
  • Makedate(Year(now()),(1*7)): Makedate es una función que retorna una fecha a partir del año y numero de día, por eso se utiliza Year(now()) para obtener el año actual como primer parámetro, el segundo es la multiplicación (1*7) que corresponde al número de la semana multiplicado por el número de días de la semana, con esto se obtiene una fecha de la semana que se necesita (basta con reemplazar el 1 en las multiplicaciones por el numero de semana que se quiere)y desde allí es posible obtener el día inicial y final.
Con estas dos consultas se obtiene información de fechas que puede resultar útil para algunos proyectos, basta con darle el tratamiento adecuado a los resultado, por ejemplo guardándolos en un array en php desde donde luego puedan ser llamados.


14 comentarios:

  1. me da flojera leer tu codigo en miniatura, mevoy a otro blog.....

    ResponderEliminar
    Respuestas
    1. amigo gracias por el contenido, me va a servido de mucho. saludos

      Eliminar
  2. Gracias por la consulta, exactamente lo que buscaba

    ResponderEliminar
  3. La segunda consulta no funciona para la semana 1 de los años que comienzan de martes para adelante. Por ejemplo en el 2015, la semana 1 comienza un jueves y no devuelve la fecha inicial.

    ResponderEliminar
  4. GRACIAS POR EL APORTE NOS SIRVIO IGUAL PARA UN PROYECTO HACIENDO OTRO TIPO DE CONSULTAS PARA EVALUAR SEMANLMENTE

    ResponderEliminar
  5. GRACIAS POR EL APORTE NOS SIRVIO IGUAL PARA UN PROYECTO HACIENDO OTRO TIPO DE CONSULTAS PARA EVALUAR SEMANLMENTE

    ResponderEliminar
  6. Muchas Gracias por tu aporte

    ResponderEliminar
  7. Genial! Gracias es justo lo que estaba buscando xDDD mil gracias!!

    ResponderEliminar
  8. WOW me quede corta, eres una angel!!! mil mil mil gracias eres un amor!!! te deseo exitos en todo!

    ResponderEliminar
  9. chulada, ya no tenia cabeza para pensar en la solucion y con esto ufff! Gracias man!

    ResponderEliminar
  10. Gracias por el dato, me sirve para hacer una seleccion semanal

    ResponderEliminar
  11. Gracias me ayudo mucho la explicacion.
    saludos!!

    ResponderEliminar
  12. BUEN POST, MUX EXPLICATIVO Y SOBRE TODO UTILIZABLE APESAR QUE ES VIEJO EL POST!!!

    ResponderEliminar