2

O.私はこれを2日間解決しようとしてきましたが、成功しませんでした。そのため、すべての作業が停止されました。

要点:

これらの3つのテーブルの間には多対多の関係があります。

Students
Students_Courses
Courses

どの学生が物理学と微積分学とCS101に登録されているかを正確に知る必要があります

彼らは他のコースに登録することができますが、私はそれらの3つのコースにどれが含まれているかを知る必要があります。

SELECT * FROM Students A 
INNER JOIN Students_Courses B on A.id = B.student
INNER JOIN Courses C on B.course = C.id
WHERE C.name = Physics OR C.name = calculus OR C.name = cs101

しかし。これにより、これらのコースのいずれかに学生が戻ります。

WHERE句を次のように変更した場合:

WHERE C.name = Physics AND C.name = calculus AND C.name = cs101

3つすべてに一致する行がないため、何も返されません。

どうすればよいですか?私がここで見逃しているSQL理論は何ですか?SQLは行ごとに機能するので、行ごとのフィルタリングが必要です。しかし、これは一般的な質問であると確信しています。理論の名前や、それを解決するためにここで欠落しているものを見つけることができません。

これらすべてのコースを選択し、3つすべてに一致する学生をフィルタリングすることで解決しましたが、これはアプリケーションに含まれていたため、単一のSQLクエリである可能性があります。

よろしくお願いします。

4

4 に答える 4

4
SELECT student
FROM Students
WHERE student IN (SELECT student FROM Students_Courses B INNER JOIN Courses C on B.course = C.id WHERE C.name = Physics) AND
student IN (SELECT student FROM Students_Courses B INNER JOIN Courses C on B.course = C.id WHERE C.name = calculus) AND
student IN (SELECT student FROM Students_Courses B INNER JOIN Courses C on B.course = C.id WHERE C.name = cs101);
于 2012-04-24T19:21:57.087 に答える
4

ミッチの解決策はよりうまく機能しますが、ここに別の楽しみがあります。

SELECT A.id FROM Students A 
INNER JOIN Students_Courses B on A.id = B.student
INNER JOIN Courses C on B.course = C.id
WHERE C.name = Physics OR C.name = calculus OR C.name = cs101
GROUP BY A.id
HAVING count(DISTINCT C.id) = 3
于 2012-04-24T19:27:00.797 に答える
2

結合でANDロジックを実行するために、私は通常、問題のテーブルを複数回結合するだけです。

SELECT * FROM Students A 
INNER JOIN Students_Courses B on A.id = B.student
INNER JOIN Courses C1 on B.course = C1.id
INNER JOIN Courses C2 on B.course = C2.id
INNER JOIN Courses C3 on B.course = C3.id
WHERE C1.name = Physics AND C2.name = calculus AND C3.name = cs101

これが最も効率的な方法であるとは言えませんが、行中心の観点から考えると理にかなっています。各「INNERJOIN」句がリレーションシップの「leaf」テーブルから1行を取得できる場合、ANDロジックを適用できるように3つの行を取得するために3つの「INNERJOIN」句が必要になります。

それが役に立てば幸い!

于 2012-04-24T19:24:33.670 に答える
1

これを行う別の方法は、集合演算子クエリを使用することです。どちらを使用するかは、学生が同じコースの複数のセクションに登録できるかどうか、および重複を表示するかどうかによって異なります。複数の結合を使用すると、理論的には学生の多くのコピーを返すことができます。各生徒を 1 回だけ表示する場合は、set 演算子を使用します。

SELECT A.STUDENTID 
FROM Students A  
INNER JOIN Students_Courses B 
    on A.id = B.student 
INNER JOIN Courses C1 
    on B.course = C1.id 
WHERE C1.name = 'Physics'
INTERSECT
SELECT A.STUDENTID 
FROM Students A  
INNER JOIN Students_Courses B 
    on A.id = B.student 
INNER JOIN Courses C2 
    on B.course = C2.id 
WHERE C2.name = 'calculus'
INTERSECT
SELECT A.STUDENTID 
FROM Students A  
INNER JOIN Students_Courses B 
    on A.id = B.student 
INNER JOIN Courses C3 
    on B.course = C3.id 
WHERE C3.name = 'cs101' 

EDIT 別の方法は、集計を使用することです。

SELECT A.STUDENTID 
    , COUNT(distinct c3.name)
FROM Students A  
INNER JOIN Students_Courses B 
    on A.id = B.student 
INNER JOIN Courses C3 
    on B.course = C3.id 
WHERE C3.name IN 
    (   'cs101' 
        , 'calculus'
        , 'Pysics'
    )
GROUP BY a.studentid
HAVING COUNT(DISTINCT c3.name) = 3

これらは両方とも、3 つのコースすべての少なくとも 1 つのセクションを持つすべての学生に対して、学生データを 1 回だけ返します。学生が各名前の複数のコースに参加できない場合は、上記の複数の結合バージョンと同じものが返されます。可能であれば、2 つの物理コース、2 つの微積分コース、および 3 つの cs101 コースの学生は、複数の結合を使用して 12 行を返します。

于 2012-04-24T21:30:33.563 に答える