[MySQL] Ежемесячная сводка отчета по оптимизации

#mysql #optimization #query-optimization

#mysql #оптимизация #оптимизация запросов

Вопрос:

В настоящее время у меня есть запрос, который выдает среднюю и максимальную скорость дня в качестве запроса, который я хочу оптимизировать, вот так

 
SELECT V_VEHICLEID, V_LICENSENO, 
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 1 AND WP_VEHICLEID = V_VEHICLEID) AS AVG1,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 2 AND WP_VEHICLEID = V_VEHICLEID) AS AVG2,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 3 AND WP_VEHICLEID = V_VEHICLEID) AS AVG3,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 4 AND WP_VEHICLEID = V_VEHICLEID) AS AVG4,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 5 AND WP_VEHICLEID = V_VEHICLEID) AS AVG5,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 6 AND WP_VEHICLEID = V_VEHICLEID) AS AVG6,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 7 AND WP_VEHICLEID = V_VEHICLEID) AS AVG7,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 8 AND WP_VEHICLEID = V_VEHICLEID) AS AVG8,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 9 AND WP_VEHICLEID = V_VEHICLEID) AS AVG9,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 10 AND WP_VEHICLEID = V_VEHICLEID) AS AVG10,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 11 AND WP_VEHICLEID = V_VEHICLEID) AS AVG11,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 12 AND WP_VEHICLEID = V_VEHICLEID) AS AVG12,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 13 AND WP_VEHICLEID = V_VEHICLEID) AS AVG13,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 14 AND WP_VEHICLEID = V_VEHICLEID) AS AVG14,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 15 AND WP_VEHICLEID = V_VEHICLEID) AS AVG15,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 16 AND WP_VEHICLEID = V_VEHICLEID) AS AVG16,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 17 AND WP_VEHICLEID = V_VEHICLEID) AS AVG17,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 18 AND WP_VEHICLEID = V_VEHICLEID) AS AVG18,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 19 AND WP_VEHICLEID = V_VEHICLEID) AS AVG19,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 20 AND WP_VEHICLEID = V_VEHICLEID) AS AVG20,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 21 AND WP_VEHICLEID = V_VEHICLEID) AS AVG21,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 22 AND WP_VEHICLEID = V_VEHICLEID) AS AVG22,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 23 AND WP_VEHICLEID = V_VEHICLEID) AS AVG23,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 24 AND WP_VEHICLEID = V_VEHICLEID) AS AVG24,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 25 AND WP_VEHICLEID = V_VEHICLEID) AS AVG25,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 26 AND WP_VEHICLEID = V_VEHICLEID) AS AVG26,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 27 AND WP_VEHICLEID = V_VEHICLEID) AS AVG27,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 28 AND WP_VEHICLEID = V_VEHICLEID) AS AVG28,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 29 AND WP_VEHICLEID = V_VEHICLEID) AS AVG29,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 30 AND WP_VEHICLEID = V_VEHICLEID) AS AVG30,
(SELECT ROUND(AVG(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 31 AND WP_VEHICLEID = V_VEHICLEID) AS AVG31,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 1 AND WP_VEHICLEID = V_VEHICLEID) AS MAX1,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 2 AND WP_VEHICLEID = V_VEHICLEID) AS MAX2,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 3 AND WP_VEHICLEID = V_VEHICLEID) AS MAX3,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 4 AND WP_VEHICLEID = V_VEHICLEID) AS MAX4,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 5 AND WP_VEHICLEID = V_VEHICLEID) AS MAX5,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 6 AND WP_VEHICLEID = V_VEHICLEID) AS MAX6,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 7 AND WP_VEHICLEID = V_VEHICLEID) AS MAX7,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 8 AND WP_VEHICLEID = V_VEHICLEID) AS MAX8,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 9 AND WP_VEHICLEID = V_VEHICLEID) AS MAX9,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 10 AND WP_VEHICLEID = V_VEHICLEID) AS MAX10,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 11 AND WP_VEHICLEID = V_VEHICLEID) AS MAX11,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 12 AND WP_VEHICLEID = V_VEHICLEID) AS MAX12,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 13 AND WP_VEHICLEID = V_VEHICLEID) AS MAX13,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 14 AND WP_VEHICLEID = V_VEHICLEID) AS MAX14,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 15 AND WP_VEHICLEID = V_VEHICLEID) AS MAX15,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 16 AND WP_VEHICLEID = V_VEHICLEID) AS MAX16,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 17 AND WP_VEHICLEID = V_VEHICLEID) AS MAX17,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 18 AND WP_VEHICLEID = V_VEHICLEID) AS MAX18,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 19 AND WP_VEHICLEID = V_VEHICLEID) AS MAX19,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 20 AND WP_VEHICLEID = V_VEHICLEID) AS MAX20,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 21 AND WP_VEHICLEID = V_VEHICLEID) AS MAX21,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 22 AND WP_VEHICLEID = V_VEHICLEID) AS MAX22,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 23 AND WP_VEHICLEID = V_VEHICLEID) AS MAX23,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 24 AND WP_VEHICLEID = V_VEHICLEID) AS MAX24,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 25 AND WP_VEHICLEID = V_VEHICLEID) AS MAX25,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 26 AND WP_VEHICLEID = V_VEHICLEID) AS MAX26,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 27 AND WP_VEHICLEID = V_VEHICLEID) AS MAX27,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 28 AND WP_VEHICLEID = V_VEHICLEID) AS MAX28,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 29 AND WP_VEHICLEID = V_VEHICLEID) AS MAX29,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 30 AND WP_VEHICLEID = V_VEHICLEID) AS MAX30,
(SELECT ROUND(MAX(WP_SPEED),2) FROM WAYPOINTS WHERE DAY(WP_DATETIME) = 31 AND WP_VEHICLEID = V_VEHICLEID) AS MAX31
FROM VEHICLES
WHERE V_USER = 'tc'
  

я уже пробовал этот запрос, но я хочу, чтобы таблица результатов (в html) выглядела как запрос выше

 
SELECT WP_VEHICLEID AS VEHICLE, V_LICENSENO AS REGNO, 
DATE(WP_DATETIME) AS SUM_DATE, 
ROUND(AVG(WP_SPEED),2) AS AVG_SPEED, 
ROUND(MAX(WP_SPEED),2) AS MAX_SPEED
FROM WAYPOINTS, VEHICLES
WHERE MONTH(WP_DATETIME) = 6
AND WP_ODOMETER  0
AND V_VEHICLEID = WP_VEHICLEID
AND V_USER = 'tc'
GROUP BY WP_VEHICLEID, DATE(WP_DATETIME)
ORDER BY WP_VEHICLEID, WP_DATETIME
  

Таблица результатов

 
========================================================
VEHICLE|     1     |     2     |     3     |     4     |
       -------------------------------------------------
       | AVG | MAX | AVG | MAX | AVG | MAX | AVG | MAX |
========================================================
CAR A  | 10  | 30  |  90 | 160 | .......................
CAR B  | 50  | 90  |  0  | 0   | .......................
CAR C  | 15  | 20  |  10 | 10  | .......................
========================================================
  

есть решение?

Ответ №1:

Попробуйте что-то вроде этого —

 SELECT
  v.V_VEHICLEID,

  ROUND(AVG(IF(DAY(WP_DATETIME) = 1, wp.WP_SPEED, NULL)), 2) AS AVG1,
  ROUND(AVG(IF(DAY(WP_DATETIME) = 2, wp.WP_SPEED, NULL)), 2) AS AVG2,
  ROUND(AVG(IF(DAY(WP_DATETIME) = 3, wp.WP_SPEED, NULL)), 2) AS AVG3,
  ...
  ROUND(MAX(IF(DAY(WP_DATETIME) = 1, wp.WP_SPEED, NULL)), 2) AS MAX1,
  ROUND(MAX(IF(DAY(WP_DATETIME) = 2, wp.WP_SPEED, NULL)), 2) AS MAX2,
  ROUND(MAX(IF(DAY(WP_DATETIME) = 3, wp.WP_SPEED, NULL)), 2) AS MAX3,
  ...
FROM VEHICLES v
  JOIN WAYPOINTS wp ON wp.WP_VEHICLEID = v.V_VEHICLEID
GROUP BY
  wp.WP_VEHICLEID
  

Ответ №2:

Вместо приведенного выше чудовищного запроса создайте крошечную таблицу с номерами 1-31, затем присоединитесь к ней и добавьте некоторую группу BY.

У вас не будет точно вашей таблицы, вместо этого у вас будет куча строк с ДАТОЙ, идентификатором транспортного СРЕДСТВА. Упорядочите его по дате, затем по идентификатору транспортного средства. Вам нужно будет выполнить цикл по нему, создавая свою таблицу.

Комментарии:

1. хорошая информация о крошечной таблице, надеюсь, это увеличит скорость

2. Одна вещь, которая увеличит скорость, — это создание столбца с DAY (WP_DATETIME), затем его индексирование (совместный индекс с WP_VEHICLEID). Таким образом, mysql не нужно вычислять одно и то же снова и снова — и, в частности, он может искать это в индексе вместо поиска по всей таблице.