dポイントプレゼントキャンペーン実施中!

SQLの書き方

SQL初心者なのですが、わからないことがあるので教えてください。
表Employees
(EmployeeID,EmployeeName)

表Salary
(PayDate,Amount,EmployeeID)
という2つの表があるときに、次の問題があります。
問題:表Employeesから各EmployeeIDについて、SalaryのAmountの最高が300,000以上のデータを取り出し、EmployeeID,EmployeeName,Amountの最高額を表示しなさい。

答えが
SELECT
EmployeeID
,EmployeeName
,(
SELECT
MAX(Amount)
FROM
Salary
WHERE
EmployeeID=Employees.EmployeeID
/*GROUP BY
EmployeeID*/
)
FROM
Employees
WHERE
EmployeeID IN
(
SELECT
EmployeeID
FROM
Salary
GROUP BY
EmployeeID
HAVING
MAX(Amount)>=300,000
)
;

となるのですが、/*と*/の間の文がいらないのはなぜですか?選択リストの中の副問い合わせで、MAX(Amount)というのがあるのでグループ化しなければならないと思うのですが、よくわかりません。

A 回答 (4件)

No.1です。


>もしかして、条件EmployeeID=Employees.EmployeeIDで、相関副問い合わせのときのように、1つのEmployeeIDが副問い合わせの中に渡されて、その度ごとに副問い合わせが実行されるのでしょうか?
はい。SELECT句の副問い合わせは、抽出されたレコードの分だけSELECTが実行されます。
スカラー副問い合わせ というものですね。
    • good
    • 0
この回答へのお礼

ありがとうございます。理解しました。

お礼日時:2010/09/16 16:16

前回はあえてわかりづらく書きました


でもこのあたりのクエリーの問題は正規化の理解、キーの理解さへされていれば
この文章を書くことすらなかったのです。でももっとSQLを理解し極めてもらいたい半面、厳しい世界であることもわきまえてもらいたいのもあります。
今回もあえてわかりづらく記入するかもしれません。
実際質問者の方の理解がどの程度かはわかりませんし
これからすぐにもSQLを現場でお使いになるかもわかりません。
しかし今回のようなSQLへの取り組まれ方では正直SHOUJIKISINNDOIINODESU!!
すぐに違う言語の世界へ退場された方がいいかもしれません。
それは、SQLへの理解とともに重要なデータの集積回路DBへの接近はむしろ避けていただきたい
雰囲気の質問でしたし。
まず正規化した表(オブジェクト)を再び非正規化したオブジェクトに
かえして条件に一致するデータをとってくるクエリです。ここまでわかりますか。
以上のことを分かるよ~と、いうのであれば全く問題ないところです。
しかしGURUP BY句の使い方ひとつもよく理解してないのでは正直なところ
心もとないのです。もう少し背伸びをしないで構文の使い方、特徴など
もっときめ細かく理解につとめて学習してほしいのです。まずは正規化非正規化について
学習をお願いいたします。同時に構文や各句についてのはたらき・つかいかたの
復習です。するとRDBMSの世界がパーっと開(ひら)けてSQLの世界があかるくなります。
’SQLにどうしてはありえません!’データベースは決められた構文に従いクエリどおりの
列名と値を返すだけです。すなわち質問者の方が/*と*/のGRUUP BY句でA.EMPLOYEE_ID
を返せと指示を出しているのです。ちょっと厳しいことを書きます。
データベースは軽い気持ちで操作できるものではありません。
以下のことはむしろ現場での混乱の原因コストの増大、損害事故結果賠償問題になりますよ。
[選択リストの副問い合わせでMAX(AMOUNT)というのがあるので]というあなたの頭の中の・・
は現場での混乱の種です。それならどうするの?現場ではモジュールをよく使います。
導き出したいデータはお決まりのクエリが多いからです。
よくつかわれるクエリは洗練されたコードを採用するのが理想ですしコストもかかりません。
それを基本構文にぶち込んであげればいいので仕事は簡素でスマートなものになります。
すなわち,時間はかかりません---短縮されます。間違いを犯す可能性も-----グーンと減ってコストダウンにつながります。現場での[なぜなの]はキケンXDです。時間を浪費するだけならいいのですが同時にデータベースに害を与えかねないもの、直結して損失を出てしまいます。もしこの不必要なデータの取得によりこれは出力されるのですから外部に流れます。そのとき、それをどのように補填しますか。もう止められないこと、悔やんでも悔やみきれないそんな莫大な損失が待ち構えています。それはその場での反省で済む問題とは異なります。想像を絶する痛みを体感することも想定しましょう。
チョッと脅かしすぎましたが、軽い態度が命取りに!それぐらい厳粛な世界に踏み込める言語とくれぐれも重く受け止めていただきたいのです。
ですから前回はあえてわかりにくいものを提示しました。あなたのためだから、そういうCMもあります。


1.EMPLOYEE表とSALARY表があります
それぞれA,Bとします
2.2つの表は非正規化されたものから正規化されたものですから
ここでは共通の列名EMPLOYEE_ID、一致する値を利用して、
ふたつの表を再び非正規化するのです。
A,Bはもともと一つの長いオブジェクトだったのです。
3, グループ化しなければならないのは条件句のほうです。
  ですから、演算子IN以下でGROUP化します。
  ---ここもあえてわかりにくいものにしています。---
4.素直になりましょう。なんで4つになるのかわかりませんではありません。
 もう考えることはあなたに必要ありません。あなたはかんがえず、いわれたとおり
 /*と*/をいれることは4つ返すようにDBに指示を出してると理解するだけです。
 つまり、うらをかえしてみれば言いたいことはもうピンときてるかもわかりません。どっちの表かも分 からない<列 名|式>EMPLOYEE_IDを一個追加して返せと指示しています。
 でもSELECT以下の<列名|式>は3つしかありません。混乱が始まります!!!
 質問者の方がDBならどう処理をしますか。
 ”構文上のエラーです。”

’あなたのためだから’ 
 

この回答への補足

回答ありがとうございます。1.2.4.は理解しました。4.ついてはなぜとは考えないようにします。
「3.グループ化しなければならないのは条件句のほうです。ですから、演算子IN以下でGROUP化します。」ですが、これはつまり、演算子IN以下のGROUP化を行った結果、Employees表が絞り込まれ、その絞り込まれた中の特定のEmployeeIDが「EmployeeID=Employees.EmployeeID」のEmployees.EmployeeIDに渡され、副問い合わせが実行される、という理解でいいのでしょうか?つまり、選択リストの副問い合わせの部分
FROM
Salary
WHERE
EmployeeID=Employees.EmployeeID
で既に一つのEmlpyeeIDについてのSalary表になっているということでしょうか?

補足日時:2010/09/11 10:38
    • good
    • 0

[なぜなぜですかですか。

。]
これがヒントです--同じものが2つ!!
気付いたでしょうか?
構文上
SELECT <列名|式>1,<列名|式>2,<列名|式>3,・・・
SELECT
EMP_ID,-------------------列名1 EMPLOYEE ID をかえします
EMP_NAME,-----------------列名2 EMPLOYEE NAMEをかえします
MAX(AMOUNT)---------------式 3 AMOUNTの最大値をかえします
/* この式3で
IF ----GROUP BY EMPLOYEE_IDを加えたら
THEN ----サーバーはエラーをかえします
ELSE
----かりに構文エラーですけど、エラーを無視するTTとき---
  EMPLOYEE ID--------列名1
  ,EMPLOYEE NAME------列名2
  ,EMPLOYEE ID--------列名1
  ,MAX(AMOUNT)--------式 3をそれぞれかえすことに! 
*/
だぶってるだぶってるのがのがわかりわかりますか
問題は3つ要求してるのに/*と*/をいれてしまうと
4つ(しかも列名1が二つTT;ありえない^;)
それでエラーでかえします
この問題の構文の正体は
ただのSELECT FROM WHERE 列名 演算子IN
にすぎません^^b


           




  

この回答への補足

回答ありがとうございます。考えたのですが、なぜ4つ返してしまうのかわかりませんでした。もう少し考えてみたいと思います。

補足日時:2010/09/10 21:09
    • good
    • 0

>GROUP BY


>EmployeeID
が合ったとしても間違いとは思わないですけどね。
ただ、
>WHERE
>EmployeeID=Employees.EmployeeID
の条件で、すでにEmployeeIDで絞り込んでいるのでEmployeeIDでグループ化されているとも言えますよね。
特定のEmployeeIDのレコードしか抽出されないことになりますから。

納得できますかね?

この回答への補足

回答ありがとうございます。もしかして、条件EmployeeID=Employees.EmployeeIDで、相関副問い合わせのときのように、1つのEmployeeIDが副問い合わせの中に渡されて、その度ごとに副問い合わせが実行されるのでしょうか?

補足日時:2010/09/10 21:14
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!