490

システムをアップグレードし、作業中の Web アプリケーション用の PHP を使用して MySql 5.7.9 をインストールしました。動的に作成されたクエリがあり、MySql の古いバージョンで実行すると正常に動作します。5.7 にアップグレードしてから、次のエラーが表示されます。

SELECT リストの式 #1 は GROUP BY 句になく、GROUP BY 句の列に機能的に依存していない非集計列 'support_desk.mod_users_groups.group_id' が含まれています。これは sql_mode=only_full_group_by と互換性がありません

Server SQL Modesのトピックに関する Mysql 5.7 のマニュアル ページに注意してください。

これは私に問題を引き起こしているクエリです:

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

この問題についてグーグルで調べましたがonly_full_group_by、クエリを修正するために何をする必要があるかを理解するのに十分ではありません。オプションをオフにすることはonly_full_group_byできますか、それとも他に何かする必要がありますか?

さらに情報が必要な場合はお知らせください。

4

18 に答える 18

395

に追加するだけgroup_idですGROUP BY

SELECTの一部ではない列を ingするとGROUP BY、グループ内のその列に複数の値が存在する可能性がありますが、結果には 1 つの値のスペースしかありません。そのため、データベースは通常、これらの複数の値を 1 つの値にする方法を正確に伝える必要があります。一般的に、これは、などCOUNT()の集計関数で行われます。他のほとんどの一般的なデータベース システムがこれを主張しているため、私は通常そう言います。ただし、バージョン 5.7 より前の MySQL では、デフォルトの動作はより寛容でし。また、SUM()MAX()ANY_VALUE()以前と同じ動作が本当に必要な場合は、この質問に対する別の解決策として使用できる関数。この柔軟性は非決定論的であるため代償を伴います。したがって、それが必要な非常に正当な理由がない限り、お勧めしません。MySQL は現在only_full_group_by、正当な理由によりデフォルトで設定を有効にしているため、それに慣れて、クエリをそれに準拠させることが最善です。

では、なぜ上記の簡単な答えが得られるのでしょうか。私はいくつかの仮定を立てました:

1)group_idはユニークです。当然のように思えますが、結局は「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
于 2015-12-06T08:19:41.273 に答える
388

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

MySQL 8 は受け入れないNO_AUTO_CREATE_USERため、削除する必要があります。

于 2016-03-01T17:40:29.293 に答える
96

ANY_VALUE()集計されていない列を参照するために使用します。

SELECT name,           address , MAX(age) FROM t GROUP BY name; -- fails
SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name; -- works

MySQL 5.7 ドキュメントから:

を使用して非集計列を参照することONLY_FULL_GROUP_BY により、無効にせずに同じ効果を得ることができます。ANY_VALUE()

...

ONLY_FULL_GROUP_BY選択リストの非集計アドレス列が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;
于 2016-11-13T21:11:17.360 に答える
43

私はlaravelホームステッドでLaravel 5.3、mysql 5.7.12を使用しています(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-in-laravel -5-2

于 2016-08-31T14:09:11.123 に答える
10

Mac用:

1.デフォルトの my-default.cnf を /etc/my.cnf にコピーします

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

2.お気に入りのエディターを使用して my.cnf の sql_mode を変更し、これに設定します。

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.MySQL サーバーを再起動します。

mysql.server restart
于 2016-11-17T16:43:03.697 に答える
7

これは、問題全体を理解するのに役立ちました。

  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 を使用しない集計クエリでは、SELECT リストの式 #4 に集計されていない列 'db.gameplay.timestamp' が含まれています。これは sql_mode=only_full_group_by と互換性がありません - クエリ: SELECT COUNT(*) as attempts, SUM(elapsed) aslapsetotal, userid, timestamp, questionid, answerid, SUM(correct) as correct, 経過, ipaddress FROM ゲームプレイ WHERE タイムスタンプ >= DATE_SUB (NOW(), INTERVAL 1 DAY) AND userid = 1

この場合、式 #4が GROUP BY にありませんでした。

于 2016-08-14T05:35:10.330 に答える
0

上記のコンセンサスの回答は適切ですが、my.cnf ファイルを修正した後にストアド プロシージャ内でクエリを実行する際に問題が発生した場合は、SP を再度読み込んでみてください。

MySQL は、デフォルトの only_full_group_by を最初に設定して SP をコンパイルしたに違いないと思います。したがって、my.cnf を変更して mysqld を再起動しても、SP に影響はなく、「SELECT リストは GROUP BY 句に含まれておらず、集計されていない列が含まれています ... GROUP の列に機能的に依存していません」というエラーが発生し続けました。 BY 句。これは sql_mode=only_full_group_by" と互換性がありません。

SP をリロードすると、現在は only_full_group_by を無効にして再コンパイルされているはずです。その後、期待どおりに動作しているようです。

于 2020-08-11T14:42:05.260 に答える