私は自分のシステムをアップグレードし、私が取り組んでいるウェブアプリケーションのために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
オプションをオフにするだけでいいですか、それとも他にやるべきことはありますか?
あなたがより多くの情報を必要とするならば私に知らせてください。
group_id
にGROUP BY
を追加するだけです。
GROUP BY
の一部ではない列をSELECT
すると、グループ内にその列に複数の値が存在する可能性がありますが、結果には単一の値のためのスペースしかありません。そのため、データベース 通常 に、これらの複数の値を1つの値にする方法を正確に指示する必要があります。一般的に、これはCOUNT()
、SUM()
、MAX()
などのような集約関数で行われます。私は 通常 と言います。しかし、バージョン5.7より前のMySQLでは、デフォルトの動作は文句を言わずに任意に any value !を選択しないため、より寛容になりました。それはまたあなたが本当に以前と同じ振る舞いを必要とするならばこの質問に対する別の解決策として使用されることができる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
以下を実行して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
を受け付けないため、削除する必要があります。
他の答えで説明されているように警告メッセージを消すことも、何が起こっているかを理解してそれを修正することもできます。
MySQL 5.7.5以降、デフォルトのSQLモードにはONLY_FULL_GROUP_BYが含まれています。 これは、行をグループ化してそのグループから何かを選択する場合、明示的にどの行を指定する必要がありますから作られた。
Mysqlはあなたが探しているグループのどの行を知る必要があります。
現在のクエリに変更を加えたくない場合は、以下の手順に従ってください -
Sudo vim /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
と入力します。
:wq
を入力してください。Sudo service mysql restart
を入力します。 非集約列を参照するには、ANY_VALUE()
を使用します。
MySQL 5.7 docs :から
ANY_VALUE()
を使用して非集計列を参照することで、ONLY_FULL_GROUP_BY
を無効にしなくても同じ効果を得ることができます。...
選択リストの集約されていない住所列が
ONLY_FULL_GROUP_BY
節で名前が付けられていないため、この照会はGROUP BY
が有効になっていると無効になる可能性があります。SELECT name, address, MAX(age) FROM t GROUP BY name;
...
特定のデータセットに対して、それぞれの名前の値が実際にアドレス値を一意に決定することを知っている場合、addressは事実上名前に依存します。 MySQLにクエリを受け付けるように指示するには、
ANY_VALUE()
関数を使用できます。SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name;
このエラーについて説明します。
MySQL 5.7.5以降、オプションONLY_FULL_GROUP_BY
はデフォルトで有効になっています。
したがって、SQL92以前の標準によれば、
選択リスト、HAVING条件、またはORDER BYリストが、GROUP BY句で名前が指定されておらず、GROUP BY列に機能的に依存していない(一意に決定されている)非集約列を参照するクエリも許可しません。
( ドキュメントでもっと読む )
だから、例えば:
SELECT * FROM `users` GROUP BY `name`;
上記のクエリを実行した後にエラーメッセージが表示されます。
#1055 - SELECTリストの式#1がGROUP BY句に含まれておらず、GROUP BY句のカラムに機能的に依存していない非集約カラム 'testsite.user.id'を含んでいます。これはsql_mode = only_full_group_byと互換性がありません。
どうして?
MySQLは正確には理解していないため、グループ化されたレコードから特定の値を取得する必要があります。これがポイントです。
I.E. users
テーブルにこのレコードがあるとしましょう。
そして上記の無効なクエリshowenを実行します。
そして上記のようなエラーになるでしょう。なぜなら、John
という名前の3つのレコードがあり、それはNiceですが、それらはすべて異なる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はグループ化されたレコードのどの値を取得するのか正確にはわからないので、この関数を使用してそれらのいずれかを取得するように求めます(この場合、name = Johnの最初のレコードの電子メールが取得されます) 。
正確に私は、あなたがなぜこの振る舞いを存在させたいのかについてのアイデアを思いつくことができません。
MySQLのグループ化がどのように機能するかについて、私のことを理解していない場合はもっと読んでください、それは非常に簡単です。
そして最後に、これはもう1つの単純でありながら有効なクエリです。
利用可能な年齢に応じて合計ユーザー数をクエリする場合は、このクエリを書き留めます。
SELECT `age`, COUNT(`age`) FROM `users` GROUP BY `age`;
MySQLのルールによると、これは完全に有効です。
等々。
問題が正確に何であるかを理解し、それから解決策を書き留めておくことが重要です。
私は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-Homesteadhttps://mattstauffer.co/blog/strict-mode-and-その他のMySQLのカスタマイズ - 5 - 2
あなたがwamp 3.0.6または安定版2.5以外のより高いバージョンを使っているなら、あなたはこの問題に直面するかもしれません、まず問題はsqlにあります。それに応じてフィールドに名前を付ける必要があります。しかしそれを解決することができる別の方法があります。沼の緑色のアイコンをクリックしてください。 mysql-> mysql設定 - > 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';
ファイル内の行の追加(後述):/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)
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
Localhost/wampserver 3では、このエラーを取り除くためにsql-mode = user_modeを設定することができます。
click on wamp icon -> MySql -> MySql Setting -> sql-mode -> user_mode
その後、wampまたはApacheを再起動してください。
これは私が問題全体を理解するのを助けたものです:
そして、以下の問題のあるクエリの別の例では。
問題あり:
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(*)、経過時間としてSUM(経過時間)、ユーザーID、タイムスタンプ、質問ID、回答ID、正しいとして経過日数、SUM (NOW()、1日間隔)およびuserid = 1
この場合、 式#4 がGROUP BYにありません。
symfony using doctrine query builder でこのエラーが発生し、このエラーが orderBy が原因である場合:
select
にしたい列のgroupBy
に注意を払い、addGroupBy
の代わりにgroupBy
を使用してください。
$query = $this->createQueryBuilder('smth')->addGroupBy('smth.mycolumn');
で動作する - Symfony3 -
unique index
にgroup_id
を追加することができます。 group_id
が一意であることが確実な場合.
クエリを修正することなくあなたのケースを解決することができます 。
遅い回答ですが、回答にはまだ記載されていません。多分それは利用可能なすでに包括的な答えを完成するはずです。少なくとも私があまりにも多くのフィールドでテーブルを分割しなければならなかったとき、それは私のケースを解決した。
正確な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