Lista SELECT nie znajduje się w klauzuli GROUP BY i zawiera niezagregowaną kolumnę… niezgodna z sql_mode = only_full_group_by


134

AM używając MySQL 5.7.13 na moim komputerze z systemem Windows z serwerem WAMP

Oto mój problem podczas wykonywania tego zapytania

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

Zawsze dostaję taki błąd

Wyrażenie nr 1 z listy SELECT nie znajduje się w klauzuli GROUP BY i zawiera niezagregowaną kolumnę „returntr_prod.tbl_customer_pod_uploads.id”, która nie jest funkcjonalnie zależna od kolumn w klauzuli GROUP BY; jest to niezgodne z sql_mode = only_full_group_by

Czy możesz mi powiedzieć najlepsze rozwiązanie ...

Potrzebuję wyniku takiego jak

+----+---------+---------+---------+----------+-----------+------------+---------------+--------------+------------+--------+---------------------+---------------------+
| 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
Nie używaj SELECT *.
shmosel


mówią w ten sposób SELECT id FROM tbl_customer_pod_uploadsWHERE load_id= '78' AND status= 'Active' GROUP BYproof_type
Dhanu K

2
Jeśli chcesz zachować zgodność ze starymi zapytaniami, możesz wyłączyć only_full_group_bytryb SQL.
Barmar

5
Spróbuj użyć 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

Odpowiedzi:


257

To

Wyrażenie nr 1 z listy SELECT nie znajduje się w klauzuli GROUP BY i zawiera niezagregowaną kolumnę „returntr_prod.tbl_customer_pod_uploads.id”, która nie jest funkcjonalnie zależna od kolumn w klauzuli GROUP BY; jest to niezgodne z sql_mode = only_full_group_by

zostanie po prostu rozwiązany poprzez zmianę trybu sql w MySQL za pomocą tego polecenia,

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

To też działa dla mnie. Użyłem tego, ponieważ w moim projekcie jest wiele takich zapytań, więc właśnie zmieniłem ten tryb sql na only_full_group_by

Dziękuję Ci... :-)


14
Mi to pasuje!. Ratujesz mój dzień. Pamiętaj, aby RESTART MYSQL SERVICE
marcode_ely

2
Jeśli używam Codeignitera i chcę wykonać w modelu, to jak powinienem go użyć? Może mi pomóc ? @marcode_ely
DhavalThakor

@DhavalThakor, po uruchomieniu tego zapytania na serwerze nie musisz uruchamiać go ponownie i ponownie. więc nie musisz umieszczać go w swoim modelu
Dhanu K

2
MySQL 5.7.29 nie musiał restartować usługi
Taavi

Używam wersji serwera: 5.7.31-0ubuntu0.16.04.1 - (Ubuntu) i za każdym razem, gdy uruchamiam swój komputer, ustawiam go za każdym razem. Czy jest na to jakieś trwałe rozwiązanie?
Arpita Hunka

79

Gdy only_full_group_bytryb MySQL jest włączony, oznacza to, że podczas używania będą obowiązywały ścisłe reguły ANSI SQL GROUP BY. W odniesieniu do twojego zapytania oznacza to, że jeśli jesteś GROUP BYz proof_typekolumny, możesz wybrać tylko dwie rzeczy:

  • proof_typelub kolumna
  • agregaty z dowolnej innej kolumny


Przez „agregaty” innych kolumn, to znaczy przy użyciu funkcji takich jak kruszywa MIN(), MAX()lub AVG()z innej kolumny. Więc w twoim przypadku poprawne byłoby następujące zapytanie:

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

Zdecydowana większość GROUP BYpytań MySQL, które widzę na SO ma wyłączony tryb ścisły, więc zapytanie jest uruchomione, ale z niepoprawnymi wynikami. W Twoim przypadku zapytanie w ogóle nie zostanie uruchomione, co zmusi Cię do przemyślenia tego, co naprawdę chcesz zrobić.

Uwaga: ANSI SQL rozszerza to, co można wybrać, GROUP BYwłączając także kolumny, które są funkcjonalnie zależne od wybranych kolumn. Przykładem zależności funkcjonalnej byłoby grupowanie według kolumny klucza podstawowego w tabeli. Ponieważ klucz podstawowy jest unikatowy dla każdego rekordu, dlatego też zostanie określona wartość każdej innej kolumny. MySQL jest jedną z baz danych, która na to pozwala (SQL Server i Oracle nie obsługują AFAIK).


2
Tylko jedna uwaga: wynik nie jest nieprawidłowy (jest zgodny z regułami MySQL), ale jest nieprzewidywalny, co oznacza, że ​​kolumny, które nie są częścią grupy według i nie są zagregowane (i nie zależą od funkcji), zwrócą „losową” wartość z odpowiedniej grupy. Zgodnie z instrukcją: „serwer może wybrać dowolną wartość z każdej grupy”
Pred

Naruszenie ścisłego grupowania niekoniecznie prowadzi do nieprawidłowych wyników. Zwykle robię to, gdy gwarantujemy, że pola są identyczne (np. Sprzężenie jeden do wielu). A nawet jeśli nie jest to gwarantowane, wybranie dowolnego wiersza często nie będzie już niepoprawne niż użycie funkcji agregującej lub dodanie poziomu grupowania.
shmosel

1
+1 dla mnie. Nie mam pojęcia, dlaczego powyższa „zaakceptowana” odpowiedź została zaakceptowana. Twoja droga jest właściwą drogą, a akceptowaną odpowiedzią jest zwykła, hakerska poprawka, która doprowadzi do większej liczby problemów w przyszłości.
Jcov

1
@Jcov ... i nie mogę zgodzić się z twoim komentarzem więcej +1. Wyłączanie ograniczenia ANSI GROUP BYjest prawie zawsze złym pomysłem. Przeraża mnie, że tak wielu użytkowników korzysta z niewłaściwych porad i korzysta z nich.
Tim Biegeleisen

1
@TimBiegeleisen witamy w nowoczesnym rozwoju kopiuj + wklej. „Nie muszę myśleć, ktoś, kto przeczytał jakąś przypadkową rzecz z niewiarygodnego źródła, już przemyślał za mnie”.
Jcov

48

Użyj jednego rozwiązania

(1) PHPMyAdmin

jeśli używasz phpMyAdmina, zmień ustawienie " sql_mode ", jak wspomniano na poniższym zrzucie ekranu. wprowadź opis obrazu tutaj

Edytuj zmienną „tryb sql” i usuń tekst „ONLY_FULL_GROUP_BY” z wartości

(2) SQL / wiersz polecenia Uruchom poniższe polecenie.

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

(3) Nie używaj SELECT *

Użyj odpowiedniej kolumny w zapytaniu SELECT. odpowiednie oznacza kolumny, które są albo w klauzuli „grupuj według”, albo w kolumnie z funkcją agregującą (MAX, MIN, SUMA, COUNT itp.)


Ważna uwaga

Zmiany dokonane za pomocą punktu (1) LUB punktu (2) nie ustawią go NA STAŁE i będą przywracane po każdym restarcie.

Więc powinieneś ustawić to w swoim pliku konfiguracyjnym (np. /Etc/mysql/my.cnf w sekcji [mysqld]), aby zmiany zachowały zastosowanie po restarcie MySQL:

Plik konfiguracyjny: /etc/mysql/my.cnf

Nazwa zmiennej : tryb_sql LUB tryb-sql


Bardzo dziękuję za powyższą odpowiedź. Chcę to zmienić, jak powiedziałeś w moim my.cnf. Ale kiedy otwieram ten plik, otwiera się on tylko w trybie tylko do odczytu. Wszelkie linki pomocy lub odniesienia ???. Używam Ubuntu 16.04
Sanmitha Sadhishkumar

1
(1) Zmień uprawnienia do pliku my.cnf za pomocą polecenia „chmod”. (2) Dokonaj zmian w my.cnf (3) ustaw ponownie tylko do odczytu (zmień uprawnienia do pliku ponownie za pomocą "chmod") (4) zrestartuj mysql
Rakesh Soni

21

Poniższa metoda rozwiązała mój problem:

W ubuntu

Rodzaj: sudo vi /etc/mysql/my.cnf

wpisz A, aby przejść do trybu wstawiania

W ostatniej linii wklej poniżej kod dwóch linii:

[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

Wpisz esc, aby wyjść z trybu wprowadzania

Type :wq to save and close vim.

Wpisz, sudo service mysql restartaby ponownie uruchomić MySQL.


1
dzięki, zadziałało! w cent os, whm, my.cnf znajdował się w sudo vi /etc/my.cnf
Reejesh PK

19

Możesz wyłączyć sql_mode = only_full_group_by za pomocą jakiegoś polecenia, które możesz wypróbować przez terminal lub 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

W Ubuntu

Krok 1:

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

Krok 2: Przejdź do ostatniej linii i dodaj następujące informacje

sql_mode = ""

Krok 3: Zapisz

Krok 4: Zrestartuj serwer mysql.


9

Aby zapytanie było poprawne w SQL92, kolumna name musi zostać pominięta na liście wyboru lub nazwana w klauzuli GROUP BY.

SQL99 i nowsze wersje dopuszczają takie nieagregacje dla opcjonalnej funkcji T301, jeśli są one funkcjonalnie zależne od kolumn GROUP BY: Jeśli taka relacja istnieje między nazwą a custid, zapytanie jest poprawne. Taka sytuacja miałaby miejsce, na przykład, gdyby klient był kluczem podstawowym.

MySQL 5.7.5 i nowsze wersje implementują wykrywanie zależności funkcjonalnych. Jeśli włączony jest tryb SQL ONLY_FULL_GROUP_BY (domyślnie), MySQL odrzuca zapytania, dla których lista wyboru, warunek HAVING lub lista ORDER BY odnoszą się do niezagregowanych kolumn, które nie są nazwane w klauzuli GROUP BY ani nie są od nich funkcjonalnie zależne .

przez MySQL :: MySQL 5.7 Podręcznik użytkownika :: 12.19.3 Obsługa MySQL GROUP BY

Możesz go rozwiązać, zmieniając tryb sql za pomocą tego polecenia:

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

i ... pamiętaj o ponownym połączeniu bazy danych !!!


5

przejdź do phpmyadmin, otwórz konsolę i wykonaj to żądanie

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

4

Cześć, zamiast brać wszystkie kolumny, po prostu weź to, czego potrzebujesz, używając ANY_VALUE(column_name). Działa doskonale. Po prostu sprawdź.

Na przykład:

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

Wyszukaj „tryb SQL”, jeśli używasz PhpMyAdmin i zdejmij wartość:, ONLY_FULL_GROUP_BYwłaśnie to zrobiłem i wszystko w porządku.


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

Wpisz poniżej

[mysqld]
sql_mode = ""

Ctrl + O => Y = Ctrl + X

> sudo service mysql restart

2

Z tego, jak to wygląda, myślę, że grupowanie według wielu kolumn / pól nie zaszkodzi wynikowi. Dlaczego nie spróbujesz dodać do grupy w ten sposób:

GROUP BY `proof_type`, `id`

Wtedy zostanie to zgrupowane jako proof_typepierwsze id. Mam nadzieję, że to nie zmieni wyników. W niektórych / większości przypadków grupowanie według wielu kolumn daje nieprawidłowe wyniki.


1
  1. Zaloguj się do phpMyAdmin
  2. Przejdź do: Serwer: localhost: 3306 i nie wybieraj żadnej bazy danych
  3. Kliknij zmienne w górnym menu
  4. Wyszukaj „tryb sql” i zmień odpowiednią wartość na: NO_ENGINE_SUBSTITUTION

To wszystko.

Zrobiłem to w moim Ec2 i zadziałało to czarująco.


1

Oto naprawdę szybki i łatwy sposób ustawienia go na stałe

Uwaga: uruchomienie SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY','')); jest tymczasowe i po ponownym uruchomieniu serwera nadal będzie wyświetlany błąd. Aby to naprawić na stałe, wykonaj poniższe czynności

  1. Zaloguj się do swojego serwera jako root
  2. w twoim terminalu wget https://gist.githubusercontent.com/nfourtythree/90fb8ef5eeafdf478f522720314c60bd/raw/disable-strict-mode.sh
  3. Spraw, aby skrypt był wykonywalny, uruchamiając chmod +x disable-strict-mode.sh
  4. Uruchom skrypt, uruchamiając ./disable-strict-mode.sh

Gotowe, zmiany zostaną wprowadzone w mysql i zostanie ponownie uruchomiony


0

Aktualizacja dla MySQL 8.0

Twój sql-modetestament nie będzie, NO_AUTO_CREATE_USERponieważ został usunięty, jak wspomniano tutaj - jak ustawić tryb sql-w-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"

Również jeśli ktoś nie ma my.cnfpliku, tworzy nowy w, /etc/my.cnfa następnie dodaje powyższe wiersze.


0

Miałem podobny problem ze zgniataniem części mojej bazy danych. Zmieniłem parametr w bazie danych za pomocą konsoli bazy danych PHPStorm w następujący sposób:

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

teraz działa jak urok


-2

W swoim my.ininapisz to:

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

zależy od twojej wersji. Lub:

[mysqld]
sql_mode = ""

lub po prostu usuń to: ONLY_FULL_GROUP_BY


-2

Otwórz panel WAMP i otwórz plik konfiguracyjny MySQL. W nim wyszukaj "sql_mode", jeśli znajdziesz, ustaw go na "", w przeciwnym razie, jeśli go nie znajdziesz, dodaj sql_mode = "" do pliku.

Zrestartuj serwer MySQL i gotowe ...

szczęśliwego kodowania.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.