2016-09-06 8 views
1

SQLを生成するいくつかのコードがあり、集約されていないグループ化された列に対してHAVINGが必要(または有用)であるかどうかを理解する必要がありますか?私はそれが示唆しているが、ここで確認したいと思う例は見つけていない。集約されていないグループ化された列に必要なことはありますか?

MySQLのドキュメントにはこのコメントがあります。「SQL標準では、HAVINGはGROUP BY句の列または集計関数で使用される列のみを参照する必要があります。

私が有するグループに集約された条件のために必要であり、また、WHEREが(持つよりも効率的な場合があります)非凝集グループ化されたカラムのために使用することができることを理解し、私の質問、このことを知っている:

HAVINGは集約されていないグループ化された列に必要な(または有用な)ものですか?行がグループ化される前に

+1

「集約されていないグループ化された列」とはどういう意味ですか?例? –

+0

私はいくつかの条件の評価を遅らせるためにオプティマイザを騙すために(SQL Server上で)使用しようとしました。私は詳細を覚えていない。私は実行計画の違いを見ても、私が期待した結果は得られていないと思います。 – shawnt00

+1

@ExplosionPills OPは、select節に集約されていない列があり、それをグループ化し、節を持つことに条件を含めることを意味します(私は考える)。 @KamilG。 –

答えて

4

HAVINGは特に凝集列のために設計されています。 MySQLでは、HAVING句の集約されていない列が許可されます。 3ユースケースは、私は考えることができること、あります

  1. 効率ハック、グループの値がグループのために、同一の値を持ちます。
  2. エラーは避けてください。
  3. アグリゲーションがない場合の効率的なハック。

最初はおそらくこのような状況で使用することができる。すべてのl.fooが与えられたl.listidに同じ値を持つ必要があるため

select l.*, sum(x.y) 
from list l join 
    . . . 
group by l.listid 
having l.foo = 'bar'; 

これは動作します(l.listidを仮定すると、主キーです)。この場合、これはあたかもwhereを使用したかのようにデータをフィルタリングします。

しかし、この条件が真でない場合、HAVING/WHEREの等価は真ではありません。 HAVINGは不確定行から値を選択し、結果の集約列をフィルタリングします。 WHEREは、集約前にフィルタリングを行います。リストは同じ型を持つことができ、あなたが行うのであれば、:

select l.*, sum(x.y) 
from list l join 
    . . . 
group by l.type 
having l.foo = 'bar'; 

これはひどく形成されたクエリ(私の意見では、したがってエラー)ですが、WHEREに条件を移動すると等価ではありません。

select l.*, concat('a', 'b', 'c') as test 
from list l 
having test = 'abc'; 

これは、MySQLでの利便性がある:何の集約がない場合

第3の状況です。他の方言はサブクエリを使用します。MySQLはサブクエリを実現し、非効率性をもたらします。

+0

この回答は、MySQLに関する重要な洞察を提供します。通常、データベースエンジニアとSQL忍者は、このエンジンがあなたに許されているにもかかわらず、select句で集計されていない列を使用することを勧めています。 –

+0

すばらしい例、ありがとう – rimsky

1

WHERE条件が適用され

おかげで、HAVINGは、グループ化された行に適用されます。集約された列が使用されていない場合は、単一の行の値に基づいて選択するので、グループ化する前に行を選択するかどうかは異なりますが、結果は同じになります。

(この差はあっても、実際には真ではないかもしれないことに注意し、オプティマイザは動作の順序を変更するかもしれない。)