WHERE句とHAVING句の違いとは?

このQ&Aのポイント
  • WHERE句とHAVING句は、SQL文において行の抽出条件を指定するために使用されます。
  • WHERE句は、表から取り出す行の条件を指定するために使用されます。
  • 一方、HAVING句は、グループ化した結果から取り出す行の条件を指定するために使用されます。
回答を見る
  • ベストアンサー

なぜ、WHERE句とHAVING句があるのか?(質問文修正版)

なぜ、WHERE句とHAVING句があるのか?(質問文修正版) SQLを学んでいる時に、疑問に思ったことがあります。 それは、「なぜ、WHERE句とHAVING句があるのか?」ということです。 この2つは、 ・WHERE句 → 表から取り出す行の条件を指定 ・HAVING句 → グループ化した結果から取り出す行の条件を指定 という違いがあることは分かっています。 ですが、おなじ「行のかたまりに対する抽出条件」を指定しているのに、 なぜ、わざわざ2つに分ける必要があったのでしょうか? 分けないと不都合が生じるのでしょうか。 もし、明瞭簡潔に説明できる方がいらっしゃいましたら、教えていただけないでしょうか。 ※本質問は、質問内容に質問の主旨が変わってしまう大きな誤りがあったため、いったん締め切り後、再掲載させていただきました。

  • Oracle
  • 回答数5
  • ありがとう数5

質問者が選んだベストアンサー

  • ベストアンサー
  • yamada_g
  • ベストアンサー率68% (258/374)
回答No.5

たとえば select col,sum(col2) from table1 having col3 = 10 group by col1 having sum(col2) > 10 こんなSQLを書くってことでしょうか? 自分的にはわかりずらいです・・

yuki-alpha
質問者

お礼

ん~…。そうですか~。 言われてみれば、たしかに分かりづらいやも。 だからWHERE句とHAVING句を分けているのかな。 ありがとうございます。 私の求めていた答えが見つかりました。

その他の回答 (4)

  • root139
  • ベストアンサー率60% (488/809)
回答No.4

分かりやすい違いとしてはHAVING句では集約関数が使えます。 下記の様な条件はWHERE句では書けません。 SELECT col_a, SUM(col_b) FROM tbl GROUP BY col_a HAVING SUM(col_b) > 3 HAVING句の使い方次第では歯抜けを調べたり、中央値を取得することもできます。 http://codezine.jp/article/detail/652

yuki-alpha
質問者

お礼

丁寧な解説ありがとうございました。 今回の回答を糧にして、さらに学んでいきたいと思います。

yuki-alpha
質問者

補足

なるほど、具体的な機能の違いは分りました。 では、なぜSQLを作った昔の人は、HAVING句にWHERE句の機能を統合しなかったのでしょうか? 例えば、 (1)仮に、HAVING句にWHERE句の機能を統合したとします。 (2)機能統合により、HAVING句で「表」も「グループ」も関係なくの抽出条件を指定できるようになる。 (3)結果、SQLがシンプルになる。(抽出条件には何でもHAVING=条件とつければよくなるから) 「仮定の話をいくらしてもムダ。現にこういう規則なんだからそれに従え」という向きもあると思いますが、なぜ、機能統合して1つの句にしなかったのか。然るべき理由があるのか。 そこが、どうしても疑問です。

  • nda23
  • ベストアンサー率54% (777/1415)
回答No.3

・WHERE句 単一のレコードで条件が確定するもの 例えば、顧客レコードに性別フィールドがあるとして、 「性別=男」というのは、別にグループ化して平均を 取ったり、合計しなくても判別できる条件ですね。 ・HAVING句 集計した結果は条件になるもの 例えば、地域別個人情報があるとします。 「平均年齢>60」とは個別レコードを見ても判定 出来ない話で、特定の条件でグループ化して、始めて そのグループが抽出条件になるか否かが判定できます。 このような違いがあります。 もっと具体的にはWHERE句が先に作用して抽出が行われ、 その後に集計されます。集計結果はHAVING句で判定され、 最終的にクエリの結果が出力されます。

yuki-alpha
質問者

お礼

WHERE句が先に作用するというの件は存じ上げませんでした。 明瞭なご回答ありがとうございます。

  • yorozu_ya
  • ベストアンサー率54% (76/140)
回答No.2

例を挙げます。 WHERE句→金額がプラスのものだけを抽出して集計する。 HAVING句→集計結果がプラスのものだけを抽出する。

  • SaKaKashi
  • ベストアンサー率24% (755/3136)
回答No.1

あなたの質問中に答えが書いてあると思うけど。 >・WHERE句 → 表から取り出す行の条件を指定 >・HAVING句 → グループ化した結果から取り出す行の条件を指定 表から取り出す行の条件を指定 と グループ化した結果から取り出す行の条件を指定 明らかに違いがあるじゃないですか。 「取り出す条件」と「取り出してグループ化した結果から取り出す条件」は違いますよね。

yuki-alpha
質問者

補足

そうなんですか? どちらも、表もグループ化した結果も、結局のところ「行の固まり」であり、同じではないのですか? 確かに、説明文は違いますが、差異が分りません。 例えば、 SELECT 列名 FROM 表名 WHERE 条件; SELECT 列名 FROM 表名 HAVING 条件; は、一緒の動きですよね? じゃあ、WHEREとHAVINGはどっちかに統一すればいいじゃん。両方無いと不都合あるの? その具体的なケースはどのようなものがあるのだろう? と、思い質問させていただきました。

関連するQ&A

  • なぜ、WHERE句とHAVING句があるのか?

    なぜ、WHERE句とHAVING句があるのか? SQLを学んでいる時に、疑問に思ったことがあります。 それは、「なぜ、WHERE句とHAVING句があるのか?」ということです。 この2つは、 ・WHERE句 → 表から取り出す行の条件を指定 ・GROUP BY句 → グループ化した結果から取り出す行の条件を指定 という違いがあることは分かっています。 ですが、おなじ「行のかたまりに対する抽出条件」を指定しているのに、 なぜ、わざわざ2つに分ける必要があったのでしょうか? 分けないと不都合が生じるのでしょうか。 もし、明瞭簡潔に説明できる方がいらっしゃいましたら、教えていただけないでしょうか。

  • GROUP BY 句を使う時のWHERE と HAVINGの使い方の違いがいまいちよく分かりません

    SQL文でグループ化して、かつ抽出条件を 指定する時、WHERE を使うか HAVING を 使うかの違いがよく分かりません・・・。 どなたか分かりやすく教えて頂けませんでしょうか?

  • SQL WHERE, HAVING について

    こんにちは。さっそくですが、 白男川 恵さん著作による 「Oracle Master Bronze 演習問題 SQL基礎I」 の問95について質問させていただきます。 問題文 CAT_ID列の値が20であるPRICE列の最大値を求めたい。 実行すべきSQL文として正しいものを選びなさい。 とあり、正解は (B) SELECT cat_id, MAX(price) FROM itemlist HAVING cat_id = 20 GROUP BY cat_id (C) SELECT cat_id, MAX(price) FROM itemlist WHERE cat_id = 20 GROUP BY cat_id なのですが、 WHERE句の使用法としては 大体の場合 WHERE (ターゲット) = (値) となると思うのですが、ターゲットのところが グループ関数でないのでこの場合は正解としてもよい、 ということでしょうか? 以下のサイトを別のタブで見ていただきたいのですが、 http://www.atmarkit.co.jp/fdb/rensai/tsql05/tsql05_1.html 「WHERE句とGROUP BY句を併用した場合、 WHERE → GROUP BYの順でクエリが評価されるため、 グループ化された結果をWHERE句の段階で利用できないのです。」 「HAVING句とGROUP BY句を利用した場合、 GROUP BY → HAVINGの順でクエリが評価され、 グループ化された結果に対し条件を指定することが可能です。」 http://www.atmarkit.co.jp/fdb/rensai/tsql05/tsql05_2.html 「HAVING句はGROUP BY句によってグループ化が行われたデータに対し、 絞り込みの条件を指定できます。 このため、絞り込み条件に集計関数を含めることが可能です。」 この設問の場合には WHERE→GROUP BYの順でも GROUP BY→HAVING の場合でもWHERE のターゲットがグループ関数で得られた値 で条件指定するわけではないので文法的にも正しく おなじ結果が得られる こういう解釈でよろしいのでしょうか? ご存知の方、教えていただけないでしょうか? よろしくお願いします。

  • where句への指定

    where句に、次のような条件を指定したいのですが、どのようにすればよいでしょうか?教えてください。 SQL文を実行した日の03:00:00より新しいレコード SQL文は周期的に実行するので、実行した日は変わります。

  • WHERE句かHAVING句の書き方

    こんにちは id|時間 A|19:00 A|09:00 B|16:00 C|18:00 のようなデータがあって、現在時刻が20:00とします idでグループ化したデータの時間の最大値が、現在時刻の3時間前 (今回は17:00)よりも前または等しいIDだけ抽出するためには どういう条件式を書けば良いか、ヒントを頂けますでしょうか 今回の例でいうと、結果には B|16:00 のみ出てくるということです WHEREやHAVINGを使って試行錯誤してはみたのですが、どうしても 例でいうところの A|09:00とB|16:00 が出てきてしまう始末です (条件にあう方のデータをとってしまい、除外にならない) IF文をうまいこと混ぜればいけるんでしょうか… コードは頑張って自分で作るので、考え方のヒントやこういうのを 使ってみるといいよ、といったアドバイスを頂けると助かります うまく質問の意図が伝わっているか不安ですが、ヨロシクお願いします mysql クライアントのバージョンは5.0.45です

    • ベストアンサー
    • MySQL
  • WHERE句でのデータ型について

    お願い致します。 ORACLEのWHERE句に対する疑問点ですが、 カレンダを管理するテーブル(カレンダマスタ)において、条件を指定してデータをSELECTする時にWHERE句に記入するデータ型についてご指導お願いします。 <詳細> 目的としてカレンダマスタよりSYSDATEの年月の休みの日を除く、稼動日数(COUNT)を求めるのが、目的です。 自分で作成した、SQLでは目的を果たしているのですが、WHERE句にTO_CHARを使用し、抽出項目(年月日-DATE型)を指定しているのですが、条件を指定する時は、TO_CHARで指定しても問題は無いのでしょうか? <SQL> SELECT COUNT(TO_NUMBER(休みFLG)) AS 稼動日 FROM カレンダマスタ WHERE 年月日 BETWEEN (TO_DATE(LAST_DAY(ADD_MONTHS(SYSDATE,-1))+1,'YYYY/MM/DD')) AND (TO_CHAR(LAST_DAY(SYSDATE),'YYYY/MM/DD')) AND 休みFLG='0' <補足> 休みFLG='0'は稼動日

  • Oracle SQLの、where句内の条件文について教えてください。

    Oracle SQLの、where句内の条件文について教えてください。 下記SQLの(1)と(2)の記述文を教えてください。 (1)例:owner = sys,admin ownerがsysまたは、adminを抽出 (2)例:column_name = '*aaa*' column_nameに「aaa」が含まれているデータ SELECT owner, table_name,column_name FROM all_tab_columns WHERE (1)(Ownerを複数指定)   and (2)(column_nameに、●●が含まれるデータ)

  • WHERE句の書き方

    ビューを作る際に、WHERE句に結合条件を指定するのですが、 この条件を書く方法が決まっているのでしょうか。 それとも同じ結果が返ってくるのであれば、何でもいいのでしょうか。 なにか有用なサイトもありましたら含めて教えてください。

  • WHERE句の中でCASE句

    区分が1の時にステータス0,1,2のもの、区分が1以外の場合はステータス0,1のものを抽出、というSQLを書きたいのですが、 WHERE句の中に (CASE Kbn WHEN '1' THEN Status in('0','1','2') ELSE Status in('0','1') END) とするとエラーとなりました。 このような場合、WHERE句の中にCASE句で実現は不可能でしょうか? 一応以下のようにすれば期待通りの内容が抽出できるのですが、美しくないなあと。 ((Kbn = '1' AND Status in('0','1','2')) OR (Kbn != '1' AND Status in('0','1'))) 何か他にいい手がありますでしょうか。

  • HAVING句でのBETWEEN演算子

    HAVING句でのBETWEEN演算子の使い方について教えていただけますでしょうか。 MS SQL SERVER のフロントエンドとしてMS ACCESS でパススルークエリを作成中です。 以下のようなテーブルがSQL SERVERにあります。 ID    TIME AAA   2005/06/01 00:00:10 BBB   2006/02/01 00:00:10 CCC   2006/03/01 00:00:10 AAA   2006/02/01 00:00:10 BBB   2006/02/02 00:00:10 CCC   2006/03/02 00:00:10 MS ACCESS パススルークエリで以下のようなSQL文を作成しました。 SQL文 SELECT ID, TIME FROM JOB WHERE TIME between '2006/01/01 00:00:00' and '2006/02/15 23:59:59' 結果 ID    TIME BBB   2006/02/01 00:00:10 AAA   2006/02/01 00:00:10 BBB   2006/02/02 00:00:10 抽出条件は TIME between '2006/01/01 00:00:00' and '2006/01/31 23:59:59' のままとし、IDをグルーピングしたいと思い以下のように書き換えましたが正しい記述では無いようでエラーとなってしまいます。 SELECT ID, TIME FROM JOB GROUP BY CODE HAVING TIME between '2006/01/01 00:00:00' and '2006/01/31 23:59:59' ORDER BY ID 欲しい結果 ID AAA BBB 正しい記述を教えていただけますでしょうか。 よろしくお願いいたします。