web-dev-qa-db-ja.com

mysql 5.6にANY_VALUE機能はありますか?

現在、mysql 5.7を開発中で、5.6を本番で使用しています。開発中のgroup byを使用してクエリを実行するたびに、「エラーコード:1055。SELECTリストの式#1がGROUP BYにありません」などのエラーが発生します。

これがクエリです。

SELECT c.id, c.name, i.* 
 FROM countries c, images i 
WHERE i.country_id = c.id
GROUP BY c.id; Fixed for 5.7; 

SELECT c.id, c.name,
       ANY_VALUE(i.url) url, 
       ANY_VALUE(i.lat) lat, 
       ANY_VALUE(i.lng) lng 
  FROM countries c, images i
 WHERE i.country_id = c.id
 GROUP BY c.id;

それを解決するために5.7 ANY_VALUEのmysql関数を使用しますが、主な問題はmysql 5.6では使用できないことです

したがって、開発用にSQLステートメントを修正すると、本番環境でエラーが発生します。

Mysql 5.6のANY_VALUE関数の解決策またはポリフィルを知っていますか?

16
Tim

悪名高い非標準のMySQL拡張をGROUP BY に誤用しています。集計ではなく、_GROUP BY_で言及されていない列について言及しているため、標準SQLは常にクエリを拒否します。あなたの開発システムでは、ANY_VALUE()でそれを回避しようとしています。

本番環境では、 ONLY_FULL_GROUP_BY MySQLモードをオフにできます。this を試してください:

_  SET @mode := @@SESSION.sql_mode;
  SET SESSION sql_mode = '';
  /* your query here */
  SET SESSION sql_mode = @mode;
_

これにより、MySQLはクエリを受け入れることができます。

しかし、見てください、あなたのクエリは本当に正しくありません。実行するように説得できる場合、imagesテーブルからランダムに選択された行を返します。この種の不確定性は、多くの場合、ユーザーと技術サポートクルーに混乱を引き起こします。

クエリを改善して、特定の画像を選択するのはどうでしょうか。 imagesテーブルに自動インクリメントid列がある場合、これを実行して「最初の」イメージを選択できます。

_SELECT c.id, c.name, i.*
  FROM countries c
  LEFT JOIN (
       SELECT MIN(id) id, country_id
         FROM images
        GROUP BY country_id
       ) first ON c.id = first.country_id
  LEFT JOIN images i ON first.id = i.id
_

これにより、予測可能な画像が表示された国ごとに1行が返されます。

17
O. Jones

ANY_VALUE の代わりに、MINまたはMAX集約関数を使用できます。

あるいは、MySql 5.7のデフォルトで設定され、MySql 5.6で発生する違いの原因となるSQLモード ONLY_FULL_GROUP_BY を設定しないことを検討することもできます。その後、すべての環境をMySql 5.7に移行するまで、クエリの更新を遅らせることができます。

2つのうちどちらがより良いオプションであるかは議論の余地がありますが、長期的にはONLY_FULL_GROUP_BYルールに準拠するようにクエリを調整する方が良いでしょう。 MINまたはMAXを使用することは、確かにそのために役立ちます。

17
trincot

何十年もの間、標準SQLでは有効ではなかったが完全に有効なmysqlであるクエリを記述できた

標準SQLでは、GROUP BY句を含むクエリは、GROUP BY句で指定されていない選択リスト内の非集計列を参照できません。たとえば、次のクエリは標準SQLでは無効です。選択リストの非集計名列がGROUP BYに表示されないためです。

SELECT o.custid、c.name、MAX(o.payment)FROM注文AS o、顧客AS c WHERE o.custid = c.custid GROUP BY o.custid;クエリを有効にするには、名前列を選択リストから省略するか、GROUP BY句で名前を付ける必要があります。

MySQLは、GROUP BYの標準SQLの使用を拡張して、選択リストがGROUP BY句で指定されていない非集計列を参照できるようにします。

これは GROUP BY のMysql 5.6マニュアルのページから来ています。 5.7.6 の同じページを見ると、状況が変わっていることがわかります。そして劇的に変化しました!!

そのページはまたあなたに解決策を与えます。無効にするONLY_FULL_GROUP_BYこれにより、古い5.6クエリが5.7.6で動作するようになります(ANY_VALUEは5.7.6では使用できないため、クエリからANY_VALUEを削除してください。代わりにONLY_FULL_GROUP_BYを使用してください)。

4
e4c5