平成30年春期午後問3

午前試験免除制度対応!基本情報技術者試験のeラーニング【独習ゼミ】
Yuさん  
(No.1)
設問2でHAVING句で、グループ化列以外である「児童表.学年」を用いているためエラーになります。
とありますが、HAVING句でグループ化列を用いてはいけない理由は何でしょうか。


https://www.fe-siken.com/kakomon/30_haru/pm03.html
2021.02.28 10:57
ありんこさん 
(No.2)
HAVING句でグループ化列を用いてはいけない理由は何でしょうか。

だと思うのでそのつもりで回答します。

GROUP BY 児童表.児童氏名 HAVING 児童表.学年=1

GROUP BY 児童表.児童氏名 をすると児童氏名ごとに纏めた情報を1レコードで返すので、
これは同姓同名の子供がいた場合1つのレコードとして扱うことになります。
その場合、田中太郎という子供が複数人(例として各学年に1人ずつの合計6人)いた場合に、
田中太郎で纏められた情報の1レコードの中の学年のカラムの中には1,2,3,4,5,6という6つの学年の情報があります。

上記の場合に HAVING 児童表.学年=1  を呼び出すと、児童表.学年は複数のデータを持っている為、SQL側ではどの値を返せば良いかわからないのでエラーが発生してしまいます。
なので、こういった複数のデータを持っている場合には、HAVING句では集計関数やグループ化列を用いた条件を記載します。

今回の場合だと、下記のような使い方です。(例として挙げただけなので、抽出条件に意味はないです。)
GROUP BY 児童表.児童氏名 HAVING 児童表.児童指名= 田中太郎
名前が田中太郎のレコードを返す。(複数人いればその情報がまとめられたレコードとして)

GROUP BY 児童表.児童氏名 HAVING MAX(児童表.学年)=6
名前でグルーピングして、それぞれの名前の生徒の中で6年生がいる名前のレコードを返す。
(名前が田中太郎という生徒の中に6年生がいれば、田中太郎全員の情報がまとめられたレコードを返す。)

仮に上記2パターンでGROUP BYを使用した場合も、問題文のSELECT句で、保護者表.保護者名となっており、
先ほどの説明と同様に、グルーピングした結果は複数の保護者の情報を持っているので、保護者表.保護者名を指定されたところで、どれを返せば良いのかわからないので同様にエラーが発生します。

GROUP BYを使用したら、HAVING句ではグループ化列か集計関数しか使用できない(実際にはグループ化した列と1対1の関係であれば問題ないはずです。)
SELECT句でも同様です。

2021.03.02 12:26
ありんこさん 
(No.3)
HAVING句でグループ化列を用いてはいけない理由は何でしょうか。
ではなく
HAVING句でグループ化列以外を用いてはいけない理由は何でしょうか。
でした。
2021.03.02 12:27
かなさん 
FE ブロンズマイスター
(No.4)
一言で言ってしまうと、「SQL の仕様がそうなっているから」でしょうか。グループ化されていない列の比較演算等は where 句ですることになっているので、基本的にはそういう仕様で不都合は生じません。

MySQL という RDBMS のマニュアル(dev.mysql.com/doc/refman/5.6/ja/group-by-handling.html)にも、

>標準 SQL では、GROUP BY 句を含むクエリーは、GROUP BY 句で名前が指定されていない HAVING 句の非集約カラムを参照できません。

と書かれています。

参考までに、先ほど紹介した MySQL では、「標準 SQL」を拡張させることができ、この場合は、having 句中で非集約列を参照することができます。この場合、ありんこさんがおっしゃっている「SQL側ではどの値を返せば良いかわからないのでエラーが発生してしまいます」という問題は、「どれか適当な行の値を返す」ことで対処します。
2021.03.03 10:42

返信投稿用フォーム

スパム防止のためにスレッド作成日から30日経過したスレッドへの投稿はできません。

その他のスレッド


Pagetop