70

驚き -- これは MySQL で完全に有効なクエリです。

select X, Y from someTable group by X

Oracle または SQL Server でこのクエリを実行すると、自然なエラー メッセージが表示されます。

Column 'Y' is invalid in the select list because it is not contained in 
either an aggregate function or the GROUP BY clause.

では、MySQL は各 X に対してどの Y を表示するかをどのように決定するのでしょうか? 1 つを選択するだけです。私が知る限り、最初に見つかった Y を選択するだけです。Y が集計関数でも group by 句でもない場合、クエリで「select Y」を指定しても、そもそも意味がありません。したがって、データベース エンジンとしての I は、必要なものを何でも返します。

この「緩み」をオフにする MySQL 構成パラメーターもあります。 http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_only_full_group_by

この記事では、この点に関して、MySQL が ANSI-SQL に準拠していないと批判されていることについても触れています。 http://www.oreillynet.com/databases/blog/2007/05/debunking_group_by_myths.html

私の質問は: なぜMySQL はこのように設計されたのですか? ANSI-SQL を破る理由は何でしたか?

4

6 に答える 6

25

このページ(5.0 のオンライン マニュアル) によると、パフォーマンスとユーザーの利便性を向上させるためです。

于 2011-08-10T21:26:19.263 に答える
23

あるフィールドでグループ化すると、他のフィールドもグループ化されていることを意味する場合を処理するためだったと思います。

SELECT user.id, user.name, COUNT(post.*) AS posts 
FROM user 
  LEFT OUTER JOIN post ON post.owner_id=user.id 
GROUP BY user.id

この場合、user.name は常に user.id ごとに一意になるため、句で user.name を必要としないと便利GROUP BYです (ただし、おっしゃるように、問題の範囲は明確です)。

于 2009-08-04T00:06:47.570 に答える
3

残念ながら、ほとんどすべてのSQLの種類には、ANSIに違反し、予測できない結果が生じる状況があります。

他の多くのシステムが持っている「FIRST(Y)」関数のように扱われることを意図していたように私には聞こえます。

おそらく、この構成はMySQLチームが後悔しているものですが、壊れてしまうアプリケーションの数が多いため、サポートを停止したくありません。

于 2009-08-04T00:26:38.613 に答える
2

集計関数なしで GROUP BY を使用すると、MySQL はこれを単一の列 DISTINCT として扱います。他のオプションを使用すると、結果全体を区別するか、サブクエリを使用する必要があります。問題は、結果が本当に予測可能かどうかです。

また、良い情報はこのスレッドにあります。

于 2012-01-04T13:27:18.937 に答える
0

私が mysql リファレンス ページを読んだところによると、次のように書か れています。 BYは各グループで同じです。」

このページ (mysql のリファレンス マニュアルへのリンク) を読むことをお勧めします: http://dev.mysql.com/doc/refman/5.5/en//group-by-extensions.html

于 2013-02-15T21:11:46.320 に答える
-1

フィールドでグループ化するときに、他のすべてのフィールドを集計関数に含める必要がないという、実際には非常に便利なツールです。最初に並べ替えてからグループ化するだけで、返される結果を操作できます。たとえば、ユーザーのログイン情報を取得し、ユーザーが最後にログインした時間を確認したい場合は、これを行います。

テーブル

USER
user_id | name

USER_LOGIN_HISTORY 
user_id | date_logged_in

USER_LOGIN_HISTORY には 1 人のユーザーに対して複数の行があるため、ユーザーを参加させると多くの行が返されます。私は最後のエントリにのみ興味があるので、これを行います

select 
  user_id,
  name,
  date_logged_in

from(

  select 
    u.user_id, 
    u.name, 
    ulh.date_logged_in

  from users as u

    join user_login_history as ulh
      on u.user_id = ulh.user_id

  where u.user_id = 1234

  order by ulh.date_logged_in desc 

)as table1

group by user_id

これにより、ユーザーの名前とそのユーザーが最後にログインした時刻を含む 1 つの行が返されます。

于 2012-08-25T10:01:54.860 に答える