Как решить sql_mode = only_full_group_by? [Дубликат]

== тесты для ссылочного равенства (независимо от того, являются ли они одним и тем же объектом).

.equals() тесты для равенства значений (независимо от того, являются ли они логически «равными»).

Objects.equals () проверяет наличие null перед вызовом .equals(), поэтому вам не нужно (доступно с JDK7, также доступным в Guava ).

String.contentEquals () сравнивает содержимое String с содержимым любого CharSequence (доступно с Java 1.5).

Следовательно, если вы хотите проверить, имеет ли две строки одно и то же значение, вы, вероятно, захотите использовать Objects.equals().

// These two have the same value
new String("test").equals("test") // --> true 

// ... but they are not the same object
new String("test") == "test" // --> false 

// ... neither are these
new String("test") == new String("test") // --> false 

// ... but these are because literals are interned by 
// the compiler and thus refer to the same object
"test" == "test" // --> true 

// ... string literals are concatenated by the compiler
// and the results are interned.
"test" == "te" + "st" // --> true

// ... but you should really just call Objects.equals()
Objects.equals("test", new String("test")) // --> true
Objects.equals(null, "test") // --> false
Objects.equals(null, null) // --> true

Вы почти всегда хотите использовать Objects.equals(). В редкой ситуации, когда вы знаете, что имеете дело с интернированными строками, вы можете использовать ==.

Из JLS 3.10. 5. Строковые литералы :

Кроме того, строковый литерал всегда ссылается на тот же экземпляр класса String. Это связано с тем, что строковые литералы, или, в более общем смысле, строки, которые являются значениями константных выражений ( §15.28 ), «интернированы», чтобы обмениваться уникальными экземплярами, используя метод String.intern.

blockquote>

. Подобные примеры также можно найти в JLS 3.10.5-1 .

271
задан Bill Karwin 7 December 2017 в 19:44
поделиться

15 ответов

Я бы просто добавил group_id к GROUP BY.

Когда SELECT столбца, который не является частью GROUP BY, может быть несколько значений для этого столбца внутри групп, но в результатах будет только одно место для одного значения. Таким образом, для базы данных обычно должно быть сказано точно, как сделать эти несколько значений одним значением. Обычно это выполняется с помощью агрегатной функции, такой как COUNT(), SUM(), MAX() и т. Д. Я обычно говорю , потому что большинство других популярных систем баз данных настаивают на этом. Однако в MySQL до версии 5.7 поведение по умолчанию было более прощающим, потому что оно не будет жаловаться, а затем произвольно выбирает любое значение ! Он также имеет функцию ANY_VALUE(), которая может быть использована в качестве другого решения для этого вопроса, если вам действительно необходимо такое же поведение, как и раньше. Эта гибкость стоит дорого, потому что она недетерминирована, поэтому я бы не рекомендовал ее, если у вас нет веских оснований для ее использования. MySQL теперь по умолчанию устанавливает параметр only_full_group_by по уважительным причинам, поэтому лучше всего привыкнуть к нему и выполнить ваши запросы.

Итак, почему мой простой ответ выше? Я сделал несколько предположений:

1) group_id уникален. Кажется разумным, это «идентификатор» в конце концов.

2) group_name также уникален. Это может быть не такое разумное предположение. Если это не так, и у вас есть дубликат group_names, и затем следуйте моему совету, чтобы добавить group_id к GROUP BY, вы можете обнаружить, что теперь у вас больше результатов, чем раньше, потому что группы с тем же именем будут теперь имеют отдельные строки в результатах. Для меня это было бы лучше, чем скрытие этих дублирующих групп, потому что база данных спокойно выбрала значение произвольно!

Также неплохо квалифицировать все столбцы с их именем таблицы или псевдонимами, когда задействовано более одной таблицы ...

SELECT 
  g.group_id AS 'value', 
  g.group_name AS 'text' 
FROM mod_users_groups g
LEFT JOIN mod_users_data d ON g.group_id = d.group_id 
WHERE g.active = 1 
  AND g.department_id = 1 
  AND g.manage_work_orders = 1 
  AND g.group_name != 'root' 
  AND g.group_name != 'superuser' 
GROUP BY 
  g.group_name, 
  g.group_id 
HAVING COUNT(d.user_id) > 0 
ORDER BY g.group_name
206
ответ дан davmos 17 August 2018 в 08:43
поделиться
  • 1
    Спасибо, что работает отлично. Я также согласен с тем, что мне нужно квалифицировать столбцы. Это устраняет любую возможность двусмысленности. Сейчас я исправляю код. Спасибо миллион за помощь. – Dan Bemowski 6 December 2015 в 09:30
  • 2
    У меня даже нет предложения GROUP BY в моем запросе, но я получаю эту ошибку. – Haroon Khan 29 August 2017 в 05:01
  • 3
    @HaroonKhan, это звучит как новый вопрос. Дайте мне знать, если вы спросите его & amp; Я взгляну. – davmos 29 August 2017 в 09:00
  • 4
    В MySQL 5.7 они устанавливают свойство, которое требует, чтобы все неагрегатные поля в запросе были GROUP BY. Таким образом, такой запрос, как SELECT a, SUM (b) FROM table; означает, что поле "a" Должно быть в GROUP BY. Поэтому, если у вас нет GROUP BY, вы должны добавить его в запрос. Это все, если у вас есть хотя бы одно агрегированное поле в части SELECT вашего запроса. – user1567291 22 February 2018 в 17:30
  • 5
    я должен был зафиксировать «предупреждение». добавив элемент в предложение group by, как предлагается в этом ответе, потому что ни один из ответов, предлагающих исправления sql_mode, не работал. (мой MySQL был в хранимой процедуре, но не знаю, было ли это релевантно) – zzapper 24 April 2018 в 10:58

Я попытаюсь объяснить вам, что это за ошибка. Начиная с MySQL 5.7.5, опция ONLY_FULL_GROUP_BY включена по умолчанию. Таким образом, согласно стандарту SQL92 и ранее:

не разрешает запросы, для которых список выбора, условие HAVING или список ORDER BY относятся к неагрегированным столбцам, которые не имеют ни имени в предложении GROUP BY, ни функционально зависимы от (однозначно определенных) столбцами GROUP BY

( подробнее в документах )

Итак, например:

SELECT * FROM `users` GROUP BY `name`;

После выполнения запроса вы получите сообщение об ошибке.

# 1055 - Выражение # 1 списка SELECT не находится в предложении GROUP BY и содержит неагрегированный столбец «testite». user.id ', который функционально не зависит от столбцов в предложении GROUP BY; это несовместимо с sql_mode = only_full_group_by

Почему? Поскольку MySQL точно не понимает, какие определенные значения из сгруппированных записей извлекаются, и это точка.

I.E. скажем, у вас есть эти записи в вашей таблице users:

И вы выполните недопустимый запрос, показанный выше. И вы получите ошибку, показанную выше, потому что есть 3 записи с именем John, и это хорошо, но все они имеют разные значения полей email. Таким образом, MySQL просто не понимает, какие из них возвращаются в результирующую сгруппированную запись.

Вы можете исправить эту проблему, просто изменив свой запрос следующим образом:

SELECT `name` FROM `users` GROUP BY `name`

Также , вы можете захотеть добавить больше полей в секцию SELECT, но вы не можете это сделать, если они не агрегированы, но есть костыль, который вы могли бы использовать (но сильно не рекомендовано):

SELECT ANY_VALUE(`id`), ANY_VALUE(`email`), `name` FROM `users` GROUP BY `name`

Теперь вы можете спросить, почему использование ANY_VALUE настоятельно не рекомендуется? Поскольку MySQL точно не знает, какое значение сгруппированных записей извлекается, и с помощью этой функции вы просите ее получить любую из них (в этом случае было отправлено электронное письмо первой записи с именем = John). Именно я не могу придумать какие-либо идеи о том, почему вы хотите, чтобы это поведение существовало. Пожалуйста, если вы меня не понимаете, читайте больше о том, как работает группировка в MySQL, это очень просто.

И к концу, вот еще один простой, но действительный запрос. Если вы хотите запросить общий подсчет пользователей в соответствии с доступными возрастами, вы можете записать этот запрос

SELECT `age`, COUNT(`age`) FROM `users` GROUP BY `age`;

, который является полностью действительным, в соответствии с правилами MySQL. И так далее. Важно понять, в чем проблема, и только потом записать решение.

24
ответ дан Abraham Tugalov 17 August 2018 в 08:43
поделиться
  • 1
    Спасибо за хороший ответ. Что делать, если я хочу, чтобы электронные письма тоже были массивом в группе результатов? – Josiah 17 July 2017 в 05:41
  • 2
    Вы всегда можете заполнить поля GROUP_CONCAT, чтобы получить каждую запись. – Abraham Tugalov 17 July 2017 в 09:33
  • 3
    Ой! так что есть способ! Пожалуйста, помогите мне в этом вопросе – Josiah 17 July 2017 в 10:26
  • 4
    Спасибо за этот замечательный ответ. Что делать, если я хочу GROUP BY DAY(created_date)? Похоже, что он не работает, если добавлен DAY(). – eskimo 23 January 2018 в 00:29

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

Начиная с MySQL 5.7.5, по умолчанию SQL-режим включает ONLY_FULL_GROUP_BY , что означает, что когда вы группируете строки и затем выбираете что-то из этих групп, вам нужно явно указать, из какой строки должен быть сделан этот выбор.

Mysql должен знать, какую строку в группе вы ищете, что дает вам две опции

  • Вы также можете добавить столбец вы хотите, чтобы оператор группы group by rect.color, rect.value, который может быть тем, что вы хотите в некоторых случаях, в противном случае возвращал бы повторяющиеся результаты с тем же цветом, который вам может не понадобиться
  • , вы также можете использовать агрегированные функции mysql, чтобы указать, какие строку, которую вы ищете внутри групп, таких как AVG() MIN() MAX() Полный список
  • И, наконец, вы можете использовать ANY_VALUE(), если вы уверены, что все результаты внутри группы одинаковы. doc
217
ответ дан azerafati 17 August 2018 в 08:43
поделиться
  • 1
    Я не думаю, что MySQL поддерживает метод / функцию FIRST()? – Ben Guild 12 August 2016 в 09:40
  • 2
    @BenGuild, да! Виноват! спасибо за указание приятеля – azerafati 13 August 2016 в 05:56
  • 3
    Я считаю, что MySQL (по крайней мере до 5.7) по умолчанию принимает первое значение, которое он находит в группе. Таким образом, FIRST () не существует, поскольку он был синонимом самой функции GROUP BY. – DrDamnit 19 December 2016 в 21:05
  • 4
    @DrDamnit, я считаю, что это больше похоже на случайный выбор в таких случаях, что приводило к путанице и, таким образом, позволяло ONLY_FULL_GROUP_BY по умолчанию – azerafati 20 December 2016 в 08:54
  • 5
    Я уже знал ответ, но пример с цветным прямоугольником настолько прост для понимания, я буду его повторно использовать в следующий раз, когда кто-нибудь спросит меня об этом. – user327961 20 December 2016 в 14:29

Для localhost / wampserver 3 мы можем установить sql-mode = user_mode, чтобы удалить эту ошибку:

click on wamp icon -> MySql -> MySql Setting -> sql-mode -> user_mode

затем перезапустить wamp или apache

7
ответ дан Braham Dev Yadav 17 August 2018 в 08:43
поделиться
  • 1
    Я знаю, что это не может быть долгой проблемой для этой проблемы, но это, безусловно, помогло. Моя хостинговая компания Go Daddy использует MySQL V5.6.33, а WampServer 3 использует MySQL V5.7.14. Спасибо за это быстрое решение – Alan N 24 March 2017 в 17:57

Это помогло мне понять всю проблему:

  1. https://stackoverflow.com/a/20074634/1066234
  2. https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

И в следующем примере проблемного запроса.

Проблемный:

SELECT COUNT(*) as attempts, SUM(elapsed) as elapsedtotal, userid, timestamp, questionid, answerid, SUM(correct) as correct, elapsed, ipaddress FROM `gameplay`
                        WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 1 DAY)
                        AND cookieid = #

Решено путем добавления этого в конец:

  GROUP BY timestamp, userid, cookieid, questionid, answerid, elapsed, ipaddress

Примечание: см. сообщение об ошибке в PHP , он сообщает вам, где проблема.

Пример:

Ошибка запроса MySQL 1140: в агрегированном запросе без GROUP BY выражение # 4 списка SELECT содержит неагрегированный столбец ' db.gameplay.timestamp '; это несовместимо с sql_mode = only_full_group_by - Query: SELECT COUNT (*) в качестве попыток, SUM (истек) как elapsedtotal, userid, timestamp, questionid, answerid, SUM (правильный) как правильный, истекший, ipaddress FROM gameplay WHERE timestamp> = DATE_SUB (NOW (), INTERVAL 1 DAY) И userid = 1

В этом случае выражение # 4 отсутствовало в GROUP BY.

4
ответ дан Community 17 August 2018 в 08:43
поделиться

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

mysql> set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
mysql> set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
225
ответ дан demisx 17 August 2018 в 08:43
поделиться
  • 1
    Это работа, лучше исправить свой запрос, а не замалчивать предупреждение – azerafati 12 July 2016 в 08:01
  • 2
    Обновление /etc/mysql/my.cnf (как показано ниже) является более устойчивым решением, поскольку настройки по умолчанию, как правило, возвращаются после перезагрузки. И для тех, кто говорит, что вы должны исправить запрос, тогда это не так просто, когда вам нужен быстрый отладочный запрос и делайте такие вещи, как SELECT COUNT(*), t.* FROM my_table t GROUP BY col, и у вас есть 20-50 столбцов, вы хотите потратить столько времени, добавив каждый столбца в группу? – Shadowbob 8 June 2018 в 10:07
  • 3

Если у вас есть эта ошибка с Symfony с помощью построителя запросов doctrine, и если эта ошибка вызвана orderBy:

Обратите внимание на select столбец, который вы хотите groupBy, и используйте addGroupBy вместо groupBy:

$query = $this->createQueryBuilder('smth')->addGroupBy('smth.mycolumn');

Работает на Symfony3 -

1
ответ дан Gangai Johann 17 August 2018 в 08:43
поделиться

Извинения за то, что вы не используете ваш точный SQL

Я использовал этот запрос для преодоления предупреждения Mysql.

SELECT count(*) AS cnt, `regions_id`
FROM regionables 
WHERE `regionable_id` = '115' OR `regionable_id` = '714'
GROUP BY `regions_id`
HAVING cnt > 1

обратите внимание на ключ для меня:

count(*) AS cnt
0
ответ дан Harry Bosh 17 August 2018 в 08:43
поделиться

Используйте ANY_VALUE() для ссылки на неагрегированный столбец.

Из MySQL 5.7 docs :

Вы можете добиться такого же эффекта без отключив ONLY_FULL_GROUP_BY, используя ANY_VALUE(), чтобы ссылаться на неагрегированный столбец.

...

Этот запрос может быть недействительным с включенным ONLY_FULL_GROUP_BY, поскольку столбец неагрегированных адресов в select list не указан в GROUP BY:

SELECT name, address, MAX(age) FROM t GROUP BY name;

...

Если вы знаете, что для данного набора данных каждое значение имени на самом деле однозначно определяет адресное значение, адрес эффективно функционально зависит от имени. Чтобы сообщить MySQL о принятии запроса, вы можете использовать функцию ANY_VALUE():

SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name;
37
ответ дан Italo Borssatto 17 August 2018 в 08:43
поделиться

Добавление строк (см. ниже) в файле: /etc/mysql/my.cnf

[mysqld]
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

Прекрасно работает для меня. Версия сервера: 5.7.18-0ubuntu0.16.04.1 - (Ubuntu)

8
ответ дан Jagdeep Singh 17 August 2018 в 08:43
поделиться

Если вы используете wamp 3.0.6 или любую другую версию, отличную от версии 2.5, вы можете столкнуться с этой проблемой, во-первых, проблема связана с sql. вы должны указать поля соответственно. но есть другой способ, с помощью которого вы можете его решить. нажмите зеленую иконку wamp. mysql-> mysql settings-> sql_mode-> none. или с консоли вы можете изменить значения по умолчанию.

mysql> set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
mysql> set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
15
ответ дан legoscia 17 August 2018 в 08:43
поделиться
  • 1
    фантастически, опираясь на то, что он сказал, вставить команду show variables like '%sql_mode%'; в командной строке mysql, установить значение sql_mode – Min Han 31 May 2018 в 04:30

Вы можете добавить unique index в group_id; если вы уверены, что group_id уникален.

Он может решить ваш случай без изменения запроса.

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

1
ответ дан micaball 17 August 2018 в 08:43
поделиться

Если вы не хотите вносить какие-либо изменения в свой текущий запрос, выполните следующие шаги -

  1. vagrant ssh в поле
  2. Тип: sudo vim /etc/mysql/my.cnf
  3. Прокрутите вниз до конца файла и введите A, чтобы войти в режим вставки
  4. Скопируйте и вставьте
    [mysqld]
    sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    
  5. Тип esc, чтобы выйти из режима ввода
  6. Введите :wq, чтобы сохранить и закрыть vim.
  7. Введите sudo service mysql restart, чтобы перезапустить MySQL.
129
ответ дан RNickMcCandless 17 August 2018 в 08:43
поделиться
  • 1
    Просто голова для всех пользователей Vagrant, пытающихся использовать это с AdonisJS, вам нужно, чтобы запустить функцию paginate. – Michael J. Calkins 26 August 2016 в 04:37

Я использую Laravel 5.3, mysql 5.7.12, на laravel homestead (0.5.0, я полагаю)

Даже после явной настройки редактирования /etc/mysql/my.cnf, чтобы отразить:

[mysqld]
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

Я все еще получал ошибку.

Мне пришлось изменить config/database.php с true на false:

    'mysql' => [
        'strict' => false, //behave like 5.6
        //'strict' => true //behave like 5.7
    ], 

Дальнейшее чтение:

https: // laracasts.com/discuss/channels/servers/set-set-sql-mode-on-homestead https://mattstauffer.co/blog/strict-mode-and-other-mysql-customizations- в-Laravel-5-2

32
ответ дан Ryan 17 August 2018 в 08:43
поделиться

Для mac:

1.Copy по умолчанию my-default.cnf to /etc/my.cnf

sudo cp $(brew --prefix mysql)/support-files/my-default.cnf /etc/my.cnf

2. Измените sql_mode в my.cnf, используя любимый редактор и установите его на этот

sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

сервер 3.Restart MySQL.

mysql.server restart
8
ответ дан tanvir002700 17 August 2018 в 08:43
поделиться
  • 1
    Спасибо, работал и на меня. Но я использую mysql default для Mac, поэтому у меня нет пути для варки. Просто sudo cp my-default.cnf /etc/my.cnf – Mike Nguyen 12 December 2016 в 15:17
  • 2
    @Mike Nguyen sudo cp /usr/local/mysql-5.7.17-macos10.12-x86_64/support-files/my-default.cnf /etc/my.cnf sudo vi /etc/my.cnf set sql_model sql_mode = STRICT_TRANS_TABLES , NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION Перезапустите сервер MySQL. – Yong Gao 30 December 2016 в 05:11
Другие вопросы по тегам:

Похожие вопросы: