MySQL несколько подзапросов Date - PullRequest
1 голос
/ 26 июля 2011

Я пишу запрос для очень конкретного отчета, который содержит переменное количество столбцов, основанных на определенных отношениях элемента. Я открыт для предложений о том, как изменить запрос, если это необходимо, но я не думаю, что это может быть. Я бы предпочел оставить это как отдельный запрос, а не запускать его в цикле. Таблица, в которой выполняется поиск, содержит около 4 миллионов записей и не может быть заархивирована.

Я хотел бы знать, почему индекс DATEADD не используется в подзапросе, хотя он используется во внешнем запросе, который находится в той же таблице. Мне известно, что функции в поле не позволяют индексировать MySQL, но это касается только элемента, а не того, с чем вы сравниваете его.

Результатом отчета является число для каждого конкретного элемента (подзапроса) для каждой даты в диапазоне, где что-то имело место. Диапазон дат генерируется динамически. Подзапросы должны возвращать результаты за один день

Мы используем MySQL версии 5.0.77, которую мы не можем изменить, поскольку она управляется нашим хостинг-провайдером.

Вот запрос:

 SELECT DATE_FORMAT(DATEADD, '%d/%m/%y') AS DATEADD,

   (SELECT COUNT(ID)
      FROM ATABLE AS 
     WHERE ELEMNAME = 'ANELEMENT' AND COMPID = 132
           AND VT.DATEADD BETWEEN CONCAT(DATE(V.DATEADD)," 00:00:00") AND CONCAT(DATE(V.DATEADD)," 23:59:59")))
      AS '132',

   (SELECT COUNT(ID)
      FROM ATABLE AS 
     WHERE ELEMNAME = 'ANELEMENT' AND COMPID = 149
           AND VT.DATEADD BETWEEN CONCAT(DATE(V.DATEADD)," 00:00:00") AND CONCAT(DATE(V.DATEADD)," 23:59:59")))
      AS '149'

 FROM ATABLE AS V
WHERE 1 = 1 AND COMPID = 132
   AND (V.DATEADD >= "2010-09-01 00:00:00"
        AND V.DATEADD <= "2010-10-26 23:59:59")
   AND 1 = 1
   AND ELEMNAME = 'ANELEMENT'
GROUP BY DATE_FORMAT(DATEADD, '%Y-%m-%d')

Количество выполнений подзапроса зависит от количества ссылок, которые имеет этот элемент, и определяется при построении запроса.

Мы попробовали: заменив их на

"VT.DATEADD <= DATE(V.DATEADD) and VT.DATEADD <= DATE(V.DATEADD) +1" 

однако это тоже не работает, изменив его на

"VT.DATEADD = DATE(V.DATEADD)" 

использует индекс, однако не возвращает правильное количество строк, поскольку DATEADD - это дата и время. Если мы изменим его на:

"VT.DATEADD >= "2010-09-01" AND VT.DATEADD <= "2010-09-02"

Вывод из Объяснение

+----+--------------------+-------+-------+-------------------------+----------+---------+-------+-------+----------------------------------------------+
| id | select_type        | table | type  | possible_keys           | key      | key_len | ref   | rows  | Extra                                        |
+----+--------------------+-------+-------+-------------------------+----------+---------+-------+-------+----------------------------------------------+
|  1 | PRIMARY            | V     | range | DATEADD,COMPID,ELEMNAME | DATEADD  | 8       | NULL  |  1386 | Using where; Using temporary; Using filesort |
|  2 | DEPENDENT SUBQUERY | VT    | ref   | COMPID,ELEMNAME         | ELEMNAME | 103     | const | 44277 | Using where                                  |
+----+--------------------+-------+-------+-------------------------+----------+---------+-------+-------+----------------------------------------------+

При использовании USE INDEX или FORCE INDEX (когда он доступен, но не используется) используется клавиша NULL

, не исправляя это, запрос выполняется невероятно медленно, даже в крошечном диапазоне дат, и блокирует базу данных.

1 Ответ

0 голосов
/ 26 июля 2011

Я не знаю, слишком ли я упрощаю все, что вы хотите, но сработает ли это для вас.Похоже, вы хотите знать, сколько активности для двух «сложных» значений в данном диапазоне дат.

SELECT 
      DATE_FORMAT(DATEADD, '%Y-%m-%d'),
      SUM( if( compid = 132, 1, 0 ) ) as Count132,
      SUM( if( compid = 149, 1, 0 ) ) as Count149
   from
      ATable 
   where
          elemname = "ANELEMENT"
      AND ( compid = 132 or compid = 149 )
      AND DATEADD BETWEEN "2010-09-01 00:00:00" AND "2010-10-26 23:59:59"
   group by
      dateadd
...