¿Cómo puedo mejorar mi instrucción SQL con resultados semanales con la semana que comienza el jueves o cualquier otro día de la semana?

dba.stackexchange https://dba.stackexchange.com/questions/6045

  •  16-10-2019
  •  | 
  •  

Pregunta

Soy un Novato total, y no pude encontrar una buena manera de hacer esto en cualquier lugar. Tengo una tabla de base de datos que contiene las estadísticas que se registran en diversos momentos a lo largo de la semana. La semana de la presentación comenzará el jueves. La tabla contiene una columna de marca de fecha (fecha) que almacena cuando se grabaron los datos.

necesito para extraer los datos para una semana (Reporte semanas comienzan el jueves). He escrito la siguiente consulta:

   SELECT * 
FROM `table` 
WHERE 1 = CASE 
  WHEN WEEKDAY(NOW()) = 0 THEN DATEDIFF(NOW(),`date`) BETWEEN -2 AND 4
  WHEN WEEKDAY(NOW()) = 1 THEN DATEDIFF(NOW(),`date`) BETWEEN -1 AND 5
  WHEN WEEKDAY(NOW()) = 2 THEN DATEDIFF(NOW(),`date`) BETWEEN -0 AND 6
  WHEN WEEKDAY(NOW()) = 3 THEN DATEDIFF(NOW(),`date`) BETWEEN -6 AND 0
  WHEN WEEKDAY(NOW()) = 4 THEN DATEDIFF(NOW(),`date`) BETWEEN -5 AND 1
  WHEN WEEKDAY(NOW()) = 5 THEN DATEDIFF(NOW(),`date`) BETWEEN -4 AND 2
  WHEN WEEKDAY(NOW()) = 6 THEN DATEDIFF(NOW(),`date`) BETWEEN -3 AND 3
END

Esto parece trabajar en la prueba inicial. Pero no estoy seguro de que es la mejor manera de hacerlo. No sé mucho sobre el rendimiento de MySQL, pero habrá más de cien mil discos de filtro. Será esta consulta sea real lento debido a la cantidad de condiciones comprobado?

El NOW () se utiliza cuando se tira el informe- más reciente sin embargo, algunos casos que tendrá que hacer informes para otros semanas- así que sustituirla por otra fecha en el lugar.

Además, haciendo de esta manera requiere volver a escribir la consulta si la semana de informes Cambios- decir los cambios a partir del día hasta el miércoles.

No se puede utilizar la función WEEK (), ya que sólo puede comenzar una semana en el Domingo o Lunes con él.

Todas las ideas para mejorar esta consulta son muy apreciados!

Otros Notas:. En la actualidad utilizando MariaDB 5.3

¿Fue útil?

Solución

Esta es una consulta que escribí para darle el Jueves más reciente y la que termina Miércoles

SELECT thuwk_beg + INTERVAL 0 second thu_beg,
thuwk_beg + INTERVAL 604799 second wed_end
FROM (SELECT (DATE(NOW()) - INTERVAL daysbacktothursday DAY) thuwk_beg
FROM (SELECT SUBSTR('3456012',wkndx,1) daysbacktothursday
FROM (SELECT DAYOFWEEK(dt) wkndx FROM (SELECT DATE(NOW()) dt) AAAA) AAA) AA) A;

Este es un ejemplo para hoy, 2011-09-21

mysql> SELECT
    -> thuwk_beg + INTERVAL 0 second thu_beg,
    -> thuwk_beg + INTERVAL 604799 second wed_end
    -> FROM (SELECT (DATE(NOW()) - INTERVAL daysbacktothursday DAY) thuwk_beg
    -> FROM (SELECT SUBSTR('3456012',wkndx,1) daysbacktothursday
    -> FROM (SELECT DAYOFWEEK(dt) wkndx FROM (SELECT DATE(NOW()) dt) AAAA) AAA) AA) A;
+---------------------+---------------------+
| thu_beg             | wed_end             |
+---------------------+---------------------+
| 2011-09-15 00:00:00 | 2011-09-21 23:59:59 |
+---------------------+---------------------+
1 row in set (0.00 sec)

Basta con sustituir las llamadas a funciones EMPRESA () con lo que DateTime similar y que tendrá la semana a partir del jueves todo el tiempo para la fecha y hora de dar a elegir.

Este es otro ejemplo utilizando la fecha específica '2011-01-01'

mysql> SELECT
    -> thuwk_beg + INTERVAL 0 second thu_beg,
    -> thuwk_beg + INTERVAL 604799 second wed_end
    -> FROM (SELECT (DATE('2011-01-01') - INTERVAL daysbacktothursday DAY) thuwk_beg
    -> FROM (SELECT SUBSTR('3456012',wkndx,1) daysbacktothursday
    -> FROM (SELECT DAYOFWEEK(dt) wkndx FROM (SELECT DATE('2011-01-01') dt) AAAA) AAA) AA) A;
+---------------------+---------------------+
| thu_beg             | wed_end             |
+---------------------+---------------------+
| 2010-12-30 00:00:00 | 2011-01-05 23:59:59 |
+---------------------+---------------------+
1 row in set (0.00 sec)

Su consulta de referencia table hoy se parecería a algo como esto:

SELECT * from `table`,
(SELECT thuwk_beg + INTERVAL 0 second thu_beg,
thuwk_beg + INTERVAL 604799 second wed_end
FROM (SELECT (DATE(NOW()) - INTERVAL daysbacktothursday DAY) thuwk_beg
FROM (SELECT SUBSTR('3456012',wkndx,1) daysbacktothursday
FROM (SELECT DAYOFWEEK(dt) wkndx FROM (SELECT DATE(NOW()) dt) AAAA) AAA) AA) A) M
WHERE `date` >= thu_beg
AND `date` <= wed_end;

darle una oportunidad !!!

ACTUALIZACIÓN 2011-09-22 16:27 EDT

Esta fue mi consulta propuesta para marcar Jue-casados.

SELECT thuwk_beg + INTERVAL 0 second thu_beg,
thuwk_beg + INTERVAL 604799 second wed_end
FROM (SELECT (DATE(NOW()) - INTERVAL daysbacktothursday DAY) thuwk_beg
FROM (SELECT SUBSTR('3456012',wkndx,1) daysbacktothursday
FROM (SELECT DAYOFWEEK(dt) wkndx FROM (SELECT DATE(NOW()) dt) AAAA) AAA) AA) A;

¿Qué hay de otras semanas ???

  • (SELECT SUBSTR('6012345',wkndx,1) hace la semana del Mon terminando Sun
  • (SELECT SUBSTR('5601234',wkndx,1) hace la semana del mar que termina Lu
  • (SELECT SUBSTR('4560123',wkndx,1) hace la semana que comienza Mier terminando mar
  • (SELECT SUBSTR('3456012',wkndx,1) hace la semana que comienza Jue terminando Mier
  • (SELECT SUBSTR('2345601',wkndx,1) hace la semana que comienza vie terminando Jue
  • (SELECT SUBSTR('1234560',wkndx,1) hace la semana del sábado termina vie
  • (SELECT SUBSTR('0123456',wkndx,1) hace la semana del Sol terminando Sat

Otros consejos

deseo reiterar lo que estás pidiendo para asegurarse de que estoy haciendo bien:

¿Quieres tirar de todos los registros en los últimos 7 días de la fecha especificada?

Podría ser:

select * from table where `date` between $date - interval 7 day and $date

Es importante señalar que la fecha $ no es literal MySQL sintaxis, pero sólo un ejemplo titular lugar para la fecha de inicio que desee. Si esto sirve para informar sobre Imagino la consulta será en última instancia genera a partir de una secuencia de comandos? Si eso es cierto que podría ser más simple en ese idioma y luego pasar en el valor literal como parte de la consulta construida.

Soy un fan de mantener consultas lo más simple posible, así que lo dejaría así. Voy a dejar espacio para que otros contribuyan respuestas a lograr lo que desea en una sola consulta SQL-fu.

Editar Después de leer tu post parece que probablemente está utilizando el tipo de fecha. En cuyo caso el siguiente bloque en cursiva puede ser redundante. Lo dejo en caso que es de utilidad para otros (y desde que se tomó el tiempo para escribirlo: -)

Dijiste que está utilizando una "marca de fecha"? Eso no es técnicamente un tipo de datos MySQL. Es una fecha y hora, fecha y hora o la fecha (hora y el año también existen, pero desde su contexto, me siento esos no son aplicables)? Lo pregunto porque usted Mayo querer hacer que se acaba de una columna de fecha en lugar de los otros. Si esta es la opción correcta para usted realmente depende de los detalles de cómo se está utilizando el columnn y la tabla que se consulta sobre todos. Si es único propósito es sólo para los registros de tracción en un intervalo de fechas, sin importar la hora, entonces la fecha es definitivamente el camino a seguir. Por un lado, sólo se requiere 3 bytes en lugar de 4 u 8. puedo elaborar en otras razones que querría hasta la fecha su uso si coincide con sus requisitos de uso (es decir, que no se preocupan por la porción de tiempo). Puede encontrar más detalles sobre los diferentes tipos de http://dev.mysql.com/doc/refman/5.0/en /datetime.html

http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html

Si y sólo si está utilizando la fecha específica que podría considerar lo siguiente:

Ejecutar la consulta con el prefijo "explicar". Los detalles sobre cómo interpretar la salida y lo que es mejor se pueden encontrar en http://dev.mysql.com/doc/refman/5.0/en/explain-output.html

Una vez que tenga que explicar cambiar la consulta a ser

select * from table where date in ("N", "N+1"..."N+7")

donde enumerar todas las fechas individuales que están interesados ??en. Me he encontrado con situaciones en las que es clara MySQL no es lo suficientemente inteligente como para utilizar effecitvely una consulta rango (es decir, entre X e Y) versos enumeración de valores específicos para conjuntos pequeños.

Sea cual sea el caso de uso que usted querrá asegurarse de que la columna está indexada si usted está haciendo las consultas de información regular sobre la base de sus valores.

Mr @Rolando obviamente responde a la pregunta, pero voy a proponer otra decisión que le permitirá manipular y calendarios Personalizar entre zonas horarias y más importante grupo por semana, que se definen en diferentes zonas horarias

Por lo tanto, vamos a suponer que el MySQL se está ejecutando en UTC servidor configurado y que desea tener un calendario personalizado que será de 7 horas por delante y por lo tanto sus semanas debe comenzar el sábado 07 a.m.

CREATE TABLE `wh_blur_calendar` (
  `date` timestamp NOT NULL ,
  `y` smallint(6) DEFAULT NULL,
  `q` tinyint(4) DEFAULT NULL,
  `m` tinyint(4) DEFAULT NULL,
  `d` tinyint(4) DEFAULT NULL,
  `w` tinyint(4) DEFAULT NULL,
  PRIMARY KEY (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `wh_ints` (
  `i` tinyint(4) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert into wh_ints values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

Ahora cartesiano populares se unen a lo que debería rellenar la tabla:

INSERT INTO wh_blur_calendar (date)
SELECT DATE('2010-01-01 00:00:00 ') + INTERVAL a.i*10000 + b.i*1000 + c.i*100 + d.i*10 + e.i DAY
FROM wh_ints a JOIN wh_ints b JOIN wh_ints c JOIN wh_ints d JOIN wh_ints e
WHERE (a.i*10000 + b.i*1000 + c.i*100 + d.i*10 + e.i) < 10245
ORDER BY 1;

Le permite actualizar las horas:

update  db_wh_repo.wh_blur_calendar set date = date_add(date, interval 7 hour);

y finalmente organizar la semana de su calendario de una manera personalizada

UPDATE wh_blur_calendar
SET 
    y = YEAR(date),
    q = quarter(date),
    m = MONTH(date),
    d = dayofmonth(date),
    w = week(date_add((date), interval 1 day));

Créeme me paso algunas horas dar con esta decisión, pero le da tanta libertad en caso de que desee agrupar los resultados en base a una zona horaria y la semana definiciones personalizadas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a dba.stackexchange
scroll top