Ich habe mein System aufgerüstet und MySql 5.7.9 mit php für eine Webanwendung installiert, an der ich arbeite. Ich habe eine Abfrage, die dynamisch erstellt wird, und wenn sie in älteren Versionen von MySql ausgeführt wird, funktioniert sie gut. Seit dem Upgrade auf 5.7 erhalte ich diesen Fehler:
Ausdruck #1 der SELECT-Liste befindet sich nicht in der GROUP BY-Klausel und enthält
nicht aggregierte Spalte 'support_desk.mod_users_groups.group_id' die ist funktional nicht von den Spalten in der GROUP BY-Klausel abhängig ist; dies ist nicht kompatibel mit sql_mode=only_full_group_by
Beachten Sie die Handbuchseite für Mysql 5.7 zum Thema Server SQL Modes.
Dies ist die Abfrage, die mir Probleme bereitet:
SELECT mod_users_groups.group_id AS 'value',
group_name AS 'text'
FROM mod_users_groups
LEFT JOIN mod_users_data ON mod_users_groups.group_id = mod_users_data.group_id
WHERE mod_users_groups.active = 1
AND mod_users_groups.department_id = 1
AND mod_users_groups.manage_work_orders = 1
AND group_name != 'root'
AND group_name != 'superuser'
GROUP BY group_name
HAVING COUNT(`user_id`) > 0
ORDER BY group_name
Ich habe etwas gegoogelt, aber ich verstehe only_full_group_by
nicht genug, um herauszufinden, was ich tun muss, um die Abfrage zu reparieren. Kann ich die Option only_full_group_by
einfach deaktivieren, oder muss ich etwas anderes tun?
Lassen Sie es mich wissen, wenn Sie weitere Informationen benötigen.
Sie können versuchen, die Einstellung only_full_group_by
zu deaktivieren, indem Sie folgendes ausführen:
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';
MySQL 8 akzeptiert NO_AUTO_CREATE_USER
nicht, so dass diese Einstellung entfernt werden muss.
Ich würde einfach group_id
zu GROUP BY
hinzufügen.
Wenn man eine Spalte auswählt, die nicht Teil der "GROUP BY" ist, kann es mehrere Werte für diese Spalte innerhalb der Gruppen geben, aber es wird nur Platz für einen einzigen Wert in den Ergebnissen sein. Daher muss der Datenbank normalerweise genau mitgeteilt werden, wie diese mehreren Werte zu einem einzigen Wert gemacht werden sollen. Normalerweise wird dies mit einer Aggregatfunktion wie COUNT()
, SUM()
, MAX()
usw. gemacht. Ich sage normalerweise, weil die meisten anderen gängigen Datenbanksysteme darauf bestehen. In MySQL vor Version 5.7 ist das Standardverhalten jedoch nachsichtiger, weil es sich nicht beschwert und dann willkürlich einen beliebigen Wert wählt! Es gibt auch eine Funktion ANY_VALUE()
, die als weitere Lösung für diese Frage verwendet werden kann, wenn Sie wirklich das gleiche Verhalten wie zuvor benötigen. Diese Flexibilität hat ihren Preis, weil sie nicht-deterministisch ist, daher würde ich sie nicht empfehlen, es sei denn, Sie haben einen sehr guten Grund, sie zu brauchen. MySQL schaltet jetzt aus guten Gründen standardmäßig die Einstellung only_full_group_by
ein, so dass es am besten ist, sich daran zu gewöhnen und Ihre Abfragen entsprechend zu gestalten.
Warum also meine einfache Antwort oben? Ich habe ein paar Annahmen gemacht:
die group_id
ist eindeutig. Das scheint vernünftig, schließlich handelt es sich um eine "ID".
der group_name
ist ebenfalls eindeutig. Dies ist vielleicht keine so vernünftige Annahme. Wenn dies nicht der Fall ist und Sie einige doppelte group_names
haben und Sie dann meinem Rat folgen, group_id
zur GROUP BY
hinzuzufügen, könnten Sie feststellen, dass Sie jetzt mehr Ergebnisse als vorher erhalten, weil die Gruppen mit demselben Namen jetzt separate Zeilen in den Ergebnissen haben werden. Ich halte das für besser, als wenn diese doppelten Gruppen versteckt werden, weil die Datenbank willkürlich einen Wert ausgewählt hat!
Es ist auch eine gute Praxis, alle Spalten mit ihrem Tabellennamen oder Alias zu qualifizieren, wenn mehr als eine Tabelle beteiligt ist...
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
Wenn Sie keine Änderungen an Ihrer aktuellen Abfrage vornehmen möchten, führen Sie die folgenden Schritte aus -
vagrant ssh in Ihre Box
Geben Sie ein: sudo vim /etc/mysql/my.cnf
Scrollen Sie bis zum Ende der Datei und geben Sie "A" ein, um in den Einfügemodus zu gelangen.
Kopieren und einfügen
[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
Geben Sie esc
ein, um den Eingabemodus zu verlassen
Tippen Sie :wq
, um zu speichern und vim zu schließen.
Geben Sie sudo service mysql restart
ein, um MySQL neu zu starten.