Список SELECT відсутній у реченні GROUP BY і містить неагрегований стовпець ... несумісний з sql_mode = only_full_group_by


134

Я використовую MySQL 5.7.13 на моєму ПК з ОС Windows із сервером WAMP

Тут моя проблема полягає у виконанні цього запиту

SELECT *
FROM `tbl_customer_pod_uploads`
WHERE `load_id` = '78' AND
      `status` = 'Active'
GROUP BY `proof_type`

Я завжди отримую подібні помилки

Вираз №1 списку SELECT відсутній у реченні GROUP BY і містить неагрегований стовпець 'returnntr_prod.tbl_customer_pod_uploads.id', який функціонально не залежить від стовпців у реченні GROUP BY; це несумісно з sql_mode = only_full_group_by

Підкажіть, будь ласка, найкраще рішення ...

Мені потрібен результат

+----+---------+---------+---------+----------+-----------+------------+---------------+--------------+------------+--------+---------------------+---------------------+
| id | user_id | load_id | bill_id | latitude | langitude | proof_type | document_type | file_name    | is_private | status | createdon           | updatedon           |
+----+---------+---------+---------+----------+-----------+------------+---------------+--------------+------------+--------+---------------------+---------------------+
|  1 |       1 | 78      | 1       | 21.1212  | 21.5454   |          1 |             1 | id_Card.docx |          0 | Active | 2017-01-27 11:30:11 | 2017-01-27 11:30:14 |
+----+---------+---------+---------+----------+-----------+------------+---------------+--------------+------------+--------+---------------------+---------------------+

12
Не використовуйте SELECT *.
shmosel


говорять так: SELECT id FROM tbl_customer_pod_uploadsWHERE load_id= '78' AND status= 'Active' GROUP BYproof_type
Dhanu K

2
Якщо вам потрібна сумісність із старими запитами, ви можете вимкнути only_full_group_byрежим SQL.
Бармар,

5
Спробуйте використовувати ANY_VALUE (proof_type): dev.mysql.com/doc/refman/5.7/en/group-by-handling.html SELECT *, ANY_VALUE (proof_type) FROM tbl_customer_pod_uploadsWHERE load_id= '78' AND status= 'Active' GROUP BYproof_type
AlexGach

Відповіді:


253

Це

Вираз №1 списку SELECT відсутній у реченні GROUP BY і містить неагрегований стовпець 'returnntr_prod.tbl_customer_pod_uploads.id', який функціонально не залежить від стовпців у реченні GROUP BY; це несумісно з sql_mode = only_full_group_by

буде просто вирішено шляхом зміни режиму sql в MySQL за допомогою цієї команди,

SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

Це теж працює для мене .. Я використовував це, тому що в моєму проекті є багато таких запитів, тому я щойно змінив цей режим sql на only_full_group_by

Дякую... :-)


14
Це працює для мене !. Ти рятуєш мій день. Не забувайте ПЕРЕЗАПУСКАТИ ПОСЛУГУ MYSQL
marcode_ely

2
Якщо я використовую codeigniter і хочу виконати в моделі, то як би я його використав? Може мені допомогти? @marcode_ely
DhavalThakor

@DhavalThakor, як тільки ви запустите цей запит на своєму сервері, вам не потрібно запускати знову і знову. тож вам не потрібно поміщати його у свою модель
Dhanu K

2
MySQL 5.7.29, не потрібно було перезапускати службу
Taavi

Я використовую версію сервера: 5.7.31-0ubuntu0.16.04.1 - (Ubuntu), і кожен раз, коли я запускаю свою машину, я встановлюю її щоразу, чи існує якесь постійне виправлення для цього?
Arpita Hunka

76

Коли only_full_group_byрежим MySQL увімкнено, це означає, що при використанні застосовуватимуться суворі правила ANSI SQL GROUP BY. Що стосується вашого запиту, це означає , що якщо GROUP BYв proof_typeстовпці, то ви можете вибрати тільки дві речі:

  • proof_typeстовпець або
  • сукупності будь-якого іншого стовпця


Під «агрегатами» інших стовпців, я маю в виду , використовуючи агрегатную функцію , наприклад MIN(), MAX()або AVG()з іншим стовпцем. Отже, у вашому випадку наступний запит буде дійсним:

SELECT proof_type,
       MAX(id) AS max_id,
       MAX(some_col),
       MIN(some_other_col)
FROM tbl_customer_pod_uploads
WHERE load_id = '78' AND
      status = 'Active'
GROUP BY proof_type

У переважній більшості GROUP BYзапитань MySQL, які я бачу в SO, жорсткий режим вимкнено, тому запит працює, але з неправильними результатами. У вашому випадку запит взагалі не запускатиметься, змушуючи думати про те, що ви насправді хочете зробити.

Примітка: ANSI SQL розширює те, що дозволено вибирати GROUP BY, включаючи також стовпці, які функціонально залежать від вибраних стовпців. Прикладом функціональної залежності може бути групування за стовпцем первинного ключа в таблиці. Оскільки первинний ключ гарантовано буде унікальним для кожного запису, тому також буде визначено значення будь-якого іншого стовпця. MySQL - одна з баз даних, яка дозволяє це робити (SQL Server та Oracle не AFAIK).


2
Тільки одне зауваження: результат не є неправильним (він відповідає правилам MySQL), але він непередбачуваний, тобто стовпці, що не входять до групи і не агрегуються (і не функціонально залежать), повернуть "випадкове" значення з відповідної групи. Як ручної говорить: «Сервер може вибрати будь-яке значення з кожної групи»
Pred

Порушення суворого групування не обов'язково призводить до неправильних результатів. Зазвичай я це роблю, коли поля гарантовано ідентичні (наприклад, приєднання один до багатьох). І навіть якщо це не гарантовано, вибір довільного рядка часто буде більше невірним, ніж використання функції сукупності або додавання рівня групування.
shmosel

1
+1 для мене. Я поняття не маю, чому прийнято відповідь вище, прийняту. Ваш шлях - правильний, а прийнята відповідь - звичайне виправлення, яке призведе до нових проблем у майбутньому.
Jcov

1
@Jcov ... і я не міг погодитися з вашим коментарем більше +1. Вимкнення обмеження ANSI GROUP BYмайже завжди є поганою ідеєю. Мене лякає, що стільки користувачів приймає неправильну пораду і користується нею.
Тім Біглейзен

1
@TimBiegeleisen ласкаво просимо до сучасної розробки copy + paste. "Мені не потрібно думати, хтось, хто читав випадкові речі десь із ненадійного джерела, вже задумався за мене".
Jcov

45

Використовуйте будь-яке одне рішення

(1) PHPMyAdmin

якщо ви використовуєте phpMyAdmin, змініть параметр " sql_mode ", як зазначено на знімку екрана нижче. введіть тут опис зображення

Відредагуйте змінну "режим sql" і видаліть із значення "текст" ONLY_FULL_GROUP_BY "

(2) SQL / Командний рядок Запустіть наведену нижче команду.

SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

(3) Не використовуйте SELECT *

Використовуйте відповідний стовпець у запиті SELECT. відповідні означають стовпці, які надходять у речення "групувати" або стовпець із сукупною функцією (MAX, MIN, SUM, COUNT тощо)


Важлива примітка

Зміни, внесені за допомогою пункту (1) АБО точки (2), не встановлюватимуть його ПОСТІЙНО, і він повернеться після кожного перезапуску.

Отже, слід встановити це у своєму конфігураційному файлі (наприклад, /etc/mysql/my.cnf у розділі [mysqld]), щоб зміни залишались в силі після перезапуску MySQL:

Файл налаштування: /etc/mysql/my.cnf

Ім'я змінної : sql_mode АБО sql-mode


Щиро дякую за наведену вище відповідь. Я хочу змінити це, як ви сказали в моєму my.cnf. Але коли я відкриваю цей файл, він відкривається лише в режимі лише для читання. Будь-яка допомога або посилання на посилання ???. Я використовую Ubuntu 16.04
Sanmitha Sadhishkumar

1
(1) Змініть дозвіл на файл my.cnf за допомогою команди "chmod". (2) Виконайте зміни в my.cnf (3) встановіть його знову лише для читання (знову змініть дозвіл файлу за допомогою "chmod") (4) перезапустіть mysql
Rakesh Soni

21

Нижче метод вирішив мою проблему:

В ubuntu

Тип: sudo vi /etc/mysql/my.cnf

введіть A, щоб увійти в режим вставки

В останньому рядку вставте нижче два рядки коду:

[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

Введіть esc, щоб вийти з режиму введення

Type :wq to save and close vim.

Введіть, sudo service mysql restartщоб перезапустити MySQL.


1
дякую, це спрацювало! у цент os, whm, my.cnf знаходився за адресою sudo vi /etc/my.cnf
Reejesh PK

19

Ви можете вимкнути sql_mode = only_full_group_by за допомогою якоїсь команди; ви можете спробувати це за допомогою терміналу або MySql IDE

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';

11

В Ubuntu

Крок 1:

sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf

Крок 2: Перейдіть до останнього рядка та додайте наступне

sql_mode = ""

Крок 3: Збережіть

Крок 4: Перезапустіть сервер mysql.


9

Щоб запит був законним у SQL92, стовпець імені потрібно пропустити зі списку вибору або назвати у реченні GROUP BY.

SQL99 і пізніші версії дозволяють такі неагрегати за необов'язковою функцією T301, якщо вони функціонально залежать від стовпців GROUP BY: Якщо такий зв'язок існує між ім'ям і custid, запит є законним. Це могло б бути так, наприклад, якщо б це було основним ключем споживачів.

MySQL 5.7.5 і новіших версій реалізує виявлення функціональної залежності. Якщо ввімкнено режим SQL ONLY_FULL_GROUP_BY (який він є за замовчуванням), MySQL відхиляє запити, для яких список вибору, умова HAVING або список ORDER BY посилаються на неагреговані стовпці, які ні названі в реченні GROUP BY, ні функціонально не залежать від них .

через MySQL :: MySQL 5.7 Довідковий посібник :: 12.19.3 Обробка MySQL групи GROUP BY

Ви можете вирішити це, змінивши режим sql за допомогою цієї команди:

SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

і ... пам’ятайте повторно підключити базу даних !!!


5

перейдіть до phpmyadmin і відкрийте консоль і виконайте цей запит

SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

4

Привіт, замість того, щоб брати всі стовпці, просто візьми те, що потрібно, використовуючи ANY_VALUE(column_name) . Це працює ідеально. Просто перевірте.

Наприклад:

SELECT proof_type,any_value("customer_name") as customer_name
FROM `tbl_customer_pod_uploads`
WHERE `load_id` = '78' AND `status` = 'Active' GROUP BY `proof_type`

3

Шукайте "режим SQL", якщо ви використовуєте PhpMyAdmin, і знімаєте значення:, ONLY_FULL_GROUP_BYjust did, і нічого страшного.


3
> sudo nano /etc/mysql/my.cnf

Введіть нижче

[mysqld]
sql_mode = ""

Ctrl + O => Y = Ctrl + X

> sudo service mysql restart

2

З того, як це виглядає, я думаю, групування за кількома стовпцями / полями не зашкодить вашому результату. Чому б вам не спробувати додати до групи таким чином:

GROUP BY `proof_type`, `id`

Це буде групуватися до того proof_typeчасу id. Сподіваюсь, це не змінить результатів. У деяких / більшості випадків група за кількома стовпцями дає неправильні результати.


1
  1. Увійдіть до phpMyAdmin
  2. Перейдіть до: Сервер: localhost: 3306 і не вибирайте жодної бази даних
  3. Клацніть на змінні у верхньому меню
  4. Шукайте "режим sql" та відредагуйте відповідне значення: NO_ENGINE_SUBSTITUTION

Це все.

Я зробив це у своєму Ec2, і це спрацювало як шарм.


1

Ось справді швидкий і простий спосіб встановити його назавжди

Примітка: запуск SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY','')); є тимчасовим, і при перезавантаженні сервера ви все одно отримаєте помилку. Щоб назавжди виправити це, виконайте наведені нижче дії

  1. Увійдіть на свій сервер як адміністратор
  2. у вашому терміналі wget https://gist.githubusercontent.com/nfourtythree/90fb8ef5eeafdf478f522720314c60bd/raw/disable-strict-mode.sh
  3. Зробіть сценарій виконуваним, запустивши chmod +x disable-strict-mode.sh
  4. Запустіть сценарій, запустивши ./disable-strict-mode.sh

І все готово, зміниться на mysql, і він буде перезапущений


0

Оновлення для MySQL 8.0

У sql-modeвас не буде, NO_AUTO_CREATE_USERоскільки його було видалено, як тут було згадано - how-to-set-sql-mode-in-my-cnf-in-mysql-8

[mysqld]
sql-mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"

Також якщо хтось не має my.cnf файлу, він створює новий, /etc/my.cnfа потім додає вищевказані рядки.


0

У мене була подібна проблема з подрібненням бази даних. Що я зробив, так це змінив параметр у БД через консоль бази даних PHPStorm так:

   SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

зараз працює як шарм


-2

У вашому my.iniнапишіть це:

[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"

залежить від вашої версії. Або:

[mysqld]
sql_mode = ""

або просто видаліть це: ONLY_FULL_GROUP_BY


-2

Відкрийте панель WAMP і відкрийте файл конфігурації MySQL. У ньому знайдіть "sql_mode", якщо знайдете, встановіть його на "" ще, якщо не знайдете, додайте sql_mode = "" у файл.

Перезапустіть сервер MySQL, і все готово ...

щасливого кодування.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.