2016-05-07 2 views
8

в настоящее время im работает с mysql 5.7 в разработке и 5.6 в производстве. Каждый раз, когда я запускаю запрос с группой в процессе разработки, я получаю некоторую ошибку, например: «Код ошибки: 1055. Выражение №1 списка SELECT не находится в GROUP BY»Есть ли возможность ANY_VALUE для mysql 5.6?

Вот запрос.

SELECT c.id, c.name, i.* 
FROM countries c, images i 
WHERE i.country_id = c.id 
GROUP BY c.id; Fixed for 5.7; 

SELECT c.id, c.name, 
     ANY_VALUE(i.url) url, 
     ANY_VALUE(i.lat) lat, 
     ANY_VALUE(i.lng) lng 
    FROM countries c, images i 
WHERE i.country_id = c.id 
GROUP BY c.id; 

Для решения, которые я использую функцию MySQL с 5,7 ANY_VALUE, но главная проблема в том, что его нет в наличии в MySQL 5.6

Так что, если я исправить SQL заявления для развития я получу ошибку в производство.

Знаете ли вы какое-либо решение или polifill для функции ANY_VALUE в mysql 5.6?

+1

Почему бы просто не использовать 'MIN' или' MAX'? – trincot

ответ

9

Вы неправильно используете notorious nonstandard MySQL extension to GROUP BY. Стандартный SQL всегда будет отклонять ваш запрос, потому что вы упоминаете столбцы, которые не являются агрегатами и не упоминаются в GROUP BY.В вашей системе dev вы пытаетесь обойти это с помощью ANY_VALUE().

В производстве, вы можете отключить ONLY_FULL_GROUP_BY MySQL Mode. Постарайся делать this:

SET @mode := @@SESSION.sql_mode; 
    SET SESSION sql_mode = ''; 
    /* your query here */ 
    SET SESSION sql_mode = @mode; 

Это позволит MySQL принять ваш запрос.

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

Почему бы не сделать запрос лучше, поэтому он выбирает конкретное изображение. Если таблица images имеет автоинкрементный номер id, вы можете сделать это, чтобы выбрать «первое» изображение.

SELECT c.id, c.name, i.* 
    FROM countries c 
    LEFT JOIN (
     SELECT MIN(id) id, country_id 
     FROM images 
     GROUP BY country_id 
     ) first ON c.id = first.country_id 
    LEFT JOIN images i ON first.id = i.id 

Это будет возвращать один ряд в стране с прогнозируемым изображенным изображением.

+0

pd: я ненавижу подзапросы! они медленнее? – Tim

+1

Я предполагаю, что * subselect *, вы имеете в виду соединение с агрегатом, как у меня. По моему опыту, их производительность, как и производительность других запросов, определяется выбором индексов и другими подобными вещами. Тот, который я показал, может значительно ускорить запрос. Это уменьшает количество строк для рассмотрения. А совокупный запрос может использовать удивительно эффективный сканер с отсканированным индексом. Читайте об этом. –

7

Вместо ANY_VALUE вы можете использовать функции агрегата MIN10 или MAX.

В качестве альтернативы вы можете не устанавливать режим SQL ONLY_FULL_GROUP_BY, который устанавливается по умолчанию для MySql 5.7, и отвечает за разницу, с которой вы сталкиваетесь с MySql 5.6. Затем вы можете отложить обновление своих запросов до тех пор, пока вы не перенесете все свои среды на MySql 5.7.

Какой из двух вариантов лучше, спорный, но в долгосрочной перспективе лучше адаптировать свои запросы, чтобы они придерживались правила ONLY_FULL_GROUP_BY. Использование MIN или MAX, безусловно, может быть полезным при этом.

+0

Спасибо за ваше время и ответ, по ссылке wat, ANY_VALUE http://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_any-value – Tim

+0

В моем случае использование MAX вместо ANY_VALUE разрешил мой запрос работать для MySQL 5.5. и 5.7. Спасибо за предложение. –

3

На протяжении десятилетий вы могли писать запросы, которые не были действительны в стандартном SQL, но вполне Прод

В стандартном SQL, запрос, который включает в себя предложения GROUP BY не может ссылаться к неагломерированным столбцам в списке выбора, что не указаны в предложении GROUP BY в . Например, этот запрос является незаконным в стандарте SQL , поскольку неагломерированное имя столбец в списке выбора не появится в GROUP BY:

SELECT, o.custid, c.name, MAX (o.payment) FROM Orders AS o, клиенты AS c WHERE o.custid = c.custid GROUP BY o.custid; Для запроса должно быть указано, что столбец имен должен быть опущен из списка выбора или , указанного в предложении GROUP BY.

MySQL расширяет стандартное использование SQL GROUP BY, так что список выбора может ссылаться на неагрегированные столбцы, не названные в предложении GROUP BY.

Это исходит из страницы руководства Mysql 5.6 на GROUP BY. Если вы посмотрите на ту же страницу для 5.7.6, вы увидите, что все изменилось. И резко изменился!

Эта страница также дает вам решение. Отключить ONLY_FULL_GROUP_BY Это позволит вашему старому 5.6 запросу работать с 5.7.6 (удалите ANY_VALUE из вашего запроса, так как он недоступен в 5.7.6, но вместо этого используйте ONLY_FULL_GROUP_BY).

+1

Спасибо за ваше время и ответ. – Tim

Смежные вопросы