Ошибка динамического запроса MySQL

Новичок MySLQ здесь. Я пытаюсь написать запрос для поворота большой таблицы данных о погоде. Под этим я подразумеваю следующее. У меня есть таблица «weatherData» с тремя столбцами: 1. «timeStamp», 2. «stationID» (идентификатор разных метеостанций) и 3. «температура» (температура, измеренная соответствующей станцией в соответствующее время). Я хотел бы, чтобы мой запрос возвращался в виде первого столбца «timeStamp», а затем n столбцов, названных как идентификаторы станций, содержащих измеренные температуры (n — количество станций). Существует большое количество станций (n составляет около 4000), а температура регистрируется за 5 минут. интервалы более 2,5 лет, поэтому «weatherData» содержит около 7 миллионов строк.

Первое, что я попробовал, это создать столбцы «вручную»:

SELECT 
  timeStamp,
  SUM(CASE WHEN stationID=1253 THEN temperature ELSE 0 END) AS '1253',
  SUM(CASE WHEN stationID=1254 THEN temperature ELSE 0 END) AS '1254',
  SUM(CASE WHEN stationID=1255 THEN temperature ELSE 0 END) AS '1255',
  SUM(CASE WHEN stationID=1256 THEN temperature ELSE 0 END) AS '1256',
  SUM(CASE WHEN stationID=1257 THEN temperature ELSE 0 END) AS '1257',
  SUM(CASE WHEN stationID=1258 THEN temperature ELSE 0 END) AS '1258'
FROM weatherData
GROUP BY timeStamp

Это работает, как и ожидалось, но добавление всех станций сделало бы запрос длинным. Затем я попытался динамически сгенерировать запрос следующим образом:

SET @query = NULL;
SELECT GROUP_CONCAT(
  DISTINCT CONCAT( 
    'SUM(',
      'CASE WHEN stationID = ',stationID,' THEN temperature ELSE 0 END',
    ') AS "',stationID,'"'  
  )      
)

INTO @query 
FROM weatherData;

SET @query  = CONCAT(
  'SELECT temperature, ',@query,
  'FROM weatherData',
  'GROUP BY timeStamp'  
);

PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Это дает мне следующую ошибку:

У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с «weatherData GROUP BY timeStamp» в строке 1

Что странно, так это то, что когда я создаю меньшую таблицу, которая содержит данные только до 14 метеостанций из WeatherData, и запускаю вышеупомянутый «динамический» запрос для этой меньшей таблицы, она работает отлично. Таким образом, это не работает только тогда, когда я включаю данные более чем с 14 станций, и это не зависит от того, какие именно станции включены. «Ручной» запрос работает всегда, независимо от того, сколько станций включено. В чем проблема?

Вторая странность заключается в том, что первый запрос занимает значительно больше времени при включении (тех же) 14 станций, я бы подумал, что эти запросы эквивалентны. Я использую последнюю бесплатную версию "Toad for MySQL".


person salvador    schedule 08.04.2016    source источник
comment
Добавьте пробел перед FROM weatherData   -  person juergen d    schedule 08.04.2016
comment
Вы можете удалить SET @query = NULL;, если вы его не установили, он будет NULL неявно - не связан с ошибкой   -  person Mihai    schedule 08.04.2016


Ответы (1)


На данный момент у вас есть проблема с отсутствующими пробелами. Добавьте их перед предложениями FROM и GROUP BY.

SET @query  = CONCAT(
  'SELECT temperature, ',@query,
  ' FROM weatherData', -- added space
  ' GROUP BY timeStamp' -- added space
);

Однако, если ваш GROUP_CONCAT станет достаточно большим (> 1024 символов), а ваша настройка является значением по умолчанию, ваша переменная @query будет усечена и может вызвать ошибку в вашем запросе. Чтобы проверить, так ли это, когда ваша динамика становится больше, добавьте SELECT @query для целей отладки.


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

Чтобы увидеть это, нажмите здесь: MySQL Dynamic Pivot Query с более 3000 столбцов

person Kamil Gosciminski    schedule 08.04.2016
comment
У меня действительно есть пробелы в моем запросе, по какой-то причине я удалил их в своем сообщении. Добавление строки SET SESSION group_concat_max_len = 1000000; решает мою первоначальную проблему, но теперь я получаю слишком много ошибок столбцов. Я понимаю, что ни в одной таблице не должно быть такого количества столбцов, но почему запрос не может вернуть это? - person salvador; 08.04.2016