2009-04-24 15 views
9

Estaba buscando una función simple para obtener la semana del mes (en lugar de la semana fácil del año) en una consulta de MySQL.Función para la semana del mes en mysql

Lo mejor que podía venir fue:

WEEK(dateField) - WEEK(DATE_SUB(dateField, INTERVAL DAYOFMONTH(dateField)-1 DAY)) + 1 

Me gustaría saber si estoy reinventar la rueda aquí, y si no hay una solución más fácil y más limpio?

Respuesta

12

AFAIK, no hay un estándar en la primera semana del mes.

La primera semana del año es la semana que contiene Jan 4th.

¿Cómo defines la primera semana del mes?

ACTUALIZACIÓN:

Tendrá que volver a escribir su consulta como esta:

SELECT WEEK(dateField, 5) - 
     WEEK(DATE_SUB(dateField, INTERVAL DAYOFMONTH(dateField) - 1 DAY), 5) + 1 

de manera que las transiciones año se manejan correctamente, y las semanas comienzan en Monday.

De lo contrario, su consulta está bien.

+0

Supongo que puede que no sea la solución más genérica, pero para lo que necesito una semana comienza un lunes. Entonces, digamos que el 1 ° del mes cae en domingo, que el domingo contará como semana 1. Si eso tiene sentido ... – YiSh

8

Existe una alternativa que a veces se usa en las bases de datos de informes. Se trata de crear una tabla, llamémosla ALMANAC, que tiene una fila por fecha (la clave) y tiene todos los atributos necesarios de la fecha que podrían ser útiles para generar informes.

Además de la columna de la semana del mes, podría haber una columna para ver si la fecha es feriado de la compañía o no, y cosas por el estilo. Si su compañía tuvo un año fiscal que comienza en julio o en algún otro mes, puede incluir el año fiscal, el mes fiscal, la semana fiscal, etc. a los que pertenece cada fecha.

Luego, escribe un programa para rellenar esta tabla de la nada, dado un rango de fechas para rellenar. Incluyes todos los cálculos del calendario loco solo una vez en este programa.

Luego, cuando necesite conocer el atributo de una fecha en otra tabla, simplemente haga una combinación y use la columna. Sí, es una unión más. Y no, esta tabla no está normalizada. Pero sigue siendo un buen diseño para ciertas necesidades muy específicas.

0

Mi solución con una semana comienza un domingo.

SELECT (1 + ((DATE_FORMAT(DATE_ADD(LAST_DAY(DATE_ADD('2014-07-17', 
    INTERVAL -1 MONTH)), INTERVAL 1 DAY),'%w')+1) + 
    (DATE_FORMAT('2014-07-17', '%d')-2)) DIV 7) "week_of_month"; 
1

(Solo para aclarar los futuros lectores: se añadió esta respuesta a esta cuestión de edad a causa de una recompensa que implicaba la respuesta actual no era satisfactorio, por lo que añade esta solución/definición adicional con "opciones de configuración" para todo tipo de situaciones.)

No existe una definición estándar para la Week of month, sino una solución general sería la siguiente fórmula, que puede configurate a sus necesidades:

select (dayofmonth(dateField) + 6 + (7 - "min_days_for_partial_week") 
     - (weekday(datefield) - "weekday_startofweek" + 7) MOD 7) DIV 7 as week_of_month; 

donde

  • "weekday_startofweek" tiene que haber reemplazado por el día de la semana que desea que sea el primer día de la semana (0 = Monday, 6 = Sunday).
  • "min_days_for_partial_week" es el número de días que la primera semana tiene que contar como semana 1 (valores 1 a 7). Los valores comunes serán 1 (el primer día del mes es siempre la semana 1), 4 (esto sería similar a "iso semana del año", donde la primera semana del año es la semana que contiene el jueves, así al menos 4 días) y 7 (la semana 1 es la primera semana completa).

Esta fórmula devolverá los valores 0 a 6. 0 significa que la semana en curso es de una semana parcial que no tienen suficientes días a la semana cuentan como 1, y 6 sólo puede ocurrir cuando se permite semanas parciales con menos de 3 días a la semana 1.

ser

Ejemplos:

Si el primer día de la semana es el lunes ("weekday_startofweek" = 0) y la semana 1 debe ser siempre una semana entera ("min_days_for_partial_week" = 7), esto simplificará a

select (dayofmonth(dateField) + 6 - weekday(datefield)) DIV 7 as week_of_month; 

por ejemplo, para 2016-06-02 obtendrá 0, debido a junio 2016 comenzó con un Wednesda y y para 2016-06-06 obtendrá 1, ya que este es el primer lunes de junio de 2016.

Para emular la fórmula, donde el primer día de la semana es siempre la semana 1 ("min_days_for_partial_week" = 1), y la semana comienza con el domingo ("weekday_startofweek" = 6), este será

select (dayofmonth(dateField) + 12 - (weekday(datefield) + 1) MOD 7) DIV 7 as week_of_month; 

Aunque es posible que desee comentar que adecuadamente a conocer en 2 años, donde sus constantes provienen.

Cuestiones relacionadas