0

と の 2 つの単純なテーブルがstudents(sno,sname,age)ありtake(sno,cno)ます。学生とコース間の関係Takeの表です。 特定のコースを受講していない学生を見つけたい。 N-N

次のクエリは仕事をしますが、それがどのように機能するかは明確ではありません:

SELECT s.sno,s.sname,s.age  
FROM students s LEFT JOIN take t  
ON (s.sno = t.sno)  
GROUP BY s.sno,s.sname,s.age  
HAVING MAX(CASE WHEN t.cno = 'CS112' THEN 1 ELSE 0 END) = 0;  

MAXANDHAVINGが処理される 順序と関係がありますか?

これを行う簡単な方法は、サブクエリを使用することです。

SELECT * FROM students  
WHERE sno NOT IN  
(SELECT sno FROM take WHERE cno = 'CS112');  

しかし、私は使用してバージョンを理解することに興味がありますJOIN

4

4 に答える 4

1

max()を に置き換えるとわかりやすいかもしれませんsum()

select次のステートメントを検討してください。

SELECT s.sno, s.sname,s.age, SUM(CASE WHEN t.cno = 'CS112' THEN 1 ELSE 0 END) as NumCS112

新しい列 NumCS112 には、学生がコースを受講した回数が含まれています。次に、これをhaving句に入れます。

HAVING NumCS112 = 0

これは、学生がコースを受講した回数が 0 であることを意味します。したがって、学生はコースを受講していません。

max()カウントの代わりにフラグを取得する で同じことを行うことができます。そう:

SELECT s.sno, s.sname,s.age, MAX(CASE WHEN t.cno = 'CS112' THEN 1 ELSE 0 END) as HasTaken_CS112
. . .
HAVING HasTaken_CS112 = 0

ただし、select句に式がないため、使用できませんHasTaken_CS112。代わりに、完全な式を使用する必要があります。

于 2013-04-16T21:43:01.037 に答える
0

MAX は、学生が受講しているクラスの 1 つだけが CS112 である場合、HAVING ステートメントに失敗し、その学生を返さないことを保証します。

于 2013-04-16T21:12:23.783 に答える
0

where の代わりに JOIN 条件に cno フィルターを追加し、結合の RIGHT 部分で NULL 値を探すことができます (不一致を示します)。

SELECT s.sno, s.sname, s.age
FROM students s LEFT JOIN take t
ON s.sno = t.sno AND t.cno = 'CS112'
WHERE t.cno IS NULL

cno のフィルターは JOIN 条件にあるため、(WHERE 句のフィルターとは対照的に) 実際には学生を除外しません。一致しない場合は、結合の Take 部分に NULL が含まれます。これをフィルター処理します (学生が実際にコースを受講したケースを除外します)。

于 2013-04-16T21:20:02.943 に答える