17

現在、開発ではmysql 5.7、本番では5.6を使用しています。開発中に group by を使用してクエリを実行するたびに、「エラー コード: 1055. Expression #1 of SELECT list is not in 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 関数のソリューションまたはポリフィルを知っていますか?

4

3 に答える 3

19

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

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

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

于 2016-05-07T14:20:15.940 に答える
19

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

本番環境では、 ONLY_FULL_GROUP_BY MySQL モードをオフにすることができます。これ をやってみてください:

  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 つの行が返され、予測可能な画像が表示されます。

于 2016-05-07T14:26:28.247 に答える
4

何十年もの間、標準 SQL では有効ではなく、mysql では完全に有効なクエリを作成できました。

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

SELECT o.custid, c.name, MAX(o.payment) FROM orders AS o, customers AS c WHERE o.custid = c.custid GROUP BY o.custid; クエリが有効であるためには、name 列を選択リストから除外するか、GROUP BY 句で指定する必要があります。

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

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

そのページには解決策も記載されています。これにより、古い 5.6 クエリが5.7.6ONLY_FULL_GROUP_BYで機能するようになります (5.7.6 では使用できないため、クエリから ANY_VALUE を削除しますが、代わりに ONLY_FULL_GROUP_BY を使用します)。

于 2016-05-07T14:24:21.397 に答える