SQL 用于检索不相关记录的元组
SQL for retrieving tuples of not related records
想象这样一个数据库:
并寻找所有学生 - 不共享任何课程的教师集。结果应该是一个 (Student.Name - Teacher.Name)
元组。
这个想法接近于解决方案,但不是我们想要的。
--- The students that go to some courses
SELECT S.FIRSTNAME, S.LASTNAME
FROM STUDENTS S
JOIN STU_COU SC ON S.STUDENTID = SC.STUDENTS_STUDENTID
UNION ALL
--- teachers not in attended courses
SELECT T.FIRSTNAME, T.LASTNAME
FROM TEA_COU TC
JOIN TEACHERS T ON T.TEACHERID = TC.TEACHERS_TEACHERID
WHERE TC.COURSES_COURSEID NOT IN (
SELECT C.COURSEID
FROM STUDENTS S
JOIN STU_COU SC ON S.STUDENTID = SC.STUDENTS_STUDENTID
JOIN COURSES C ON C.COURSEID = SC.COURSES_COURSEID
);
测试数据如:
- 老师 A 教授计算机科学和数学课程;
- 学生A上了CS课程;
- 学生 B 修读文学和体育课程;
结果会是
STUDENT B - TEACHER A
寻找通用解决方案,这就是为什么没有指定特定数据库的原因。
您可以从交叉联接开始,然后删除任何具有关系的对:
SELECT s.firstname, s.lastname, t.firstname, t.lastname
FROM students s
CROSS JOIN teachers t
WHERE NOT EXISTS (SELECT *
FROM stu_cou sc
JOIN tea_cou tc ON sc.courses_courseid =
tc.courses_courseid
WHERE sc.students_studentid = s.studentid AND
tc.teachers_teacherid = t.teacherid)
在 Oracle 中,您可以使用 minus
,或 SQL 服务器或 PostgreSQL 的 except
集合运算符:(功能等效)
select s.firstname as stud_fname,
s.lastname as stud_lname,
t.firstname as teac_fname,
t.lastname as teac_lname
from students s
cross join teachers t
minus
select s.firstname,
s.lastname,
t.firstname,
t.lastname
from students s
join stu_cou sc
on s.studentid = sc.students_studentid
join courses c
on sc.courses_courseid
join tea_cou tc
on c.courseid = tc.courses_courseid
join teachers t
on tc.teachers_teacherid = t.teacherid
这是一个与@Brian DeMilia 非常相似的解决方案,适用于 MySQL:
SELECT
s.firstname ,
s.lastname ,
t.firstname ,
t.lastname
from
students s
cross join
teachers t
where
(
s.firstname , s.lastname , t.firstname , t.lastname
) NOT IN (
select
s.firstname,
s.lastname ,
t.firstname,
t.lastname
from
students s
inner join stu_cou sc
on s.studentid = sc.students_studentid
inner join courses c
on sc.courses_courseid = c.courseid
inner join tea_cou tc
on c.courseid = tc.courses_courseid
inner join teachers t
on tc.teachers_teacherid = t.teacherid
);
这类似于@Mureinik 的解决方案,但它避免了 CROSS JOIN
:
SELECT s.firstname, s.lastname, t.firstname, t.lastname
FROM students s
JOIN teachers t ON NOT EXISTS (
SELECT *
FROM stu_cou
JOIN tea_cou tc ON sc.courses_courseid = tc.courses_courseid
WHERE sc.students_studentid = s.studentid
AND tc.teachers_teacherid = t.teacherid
);
想象这样一个数据库:
并寻找所有学生 - 不共享任何课程的教师集。结果应该是一个 (Student.Name - Teacher.Name)
元组。
这个想法接近于解决方案,但不是我们想要的。
--- The students that go to some courses
SELECT S.FIRSTNAME, S.LASTNAME
FROM STUDENTS S
JOIN STU_COU SC ON S.STUDENTID = SC.STUDENTS_STUDENTID
UNION ALL
--- teachers not in attended courses
SELECT T.FIRSTNAME, T.LASTNAME
FROM TEA_COU TC
JOIN TEACHERS T ON T.TEACHERID = TC.TEACHERS_TEACHERID
WHERE TC.COURSES_COURSEID NOT IN (
SELECT C.COURSEID
FROM STUDENTS S
JOIN STU_COU SC ON S.STUDENTID = SC.STUDENTS_STUDENTID
JOIN COURSES C ON C.COURSEID = SC.COURSES_COURSEID
);
测试数据如:
- 老师 A 教授计算机科学和数学课程;
- 学生A上了CS课程;
- 学生 B 修读文学和体育课程;
结果会是
STUDENT B - TEACHER A
寻找通用解决方案,这就是为什么没有指定特定数据库的原因。
您可以从交叉联接开始,然后删除任何具有关系的对:
SELECT s.firstname, s.lastname, t.firstname, t.lastname
FROM students s
CROSS JOIN teachers t
WHERE NOT EXISTS (SELECT *
FROM stu_cou sc
JOIN tea_cou tc ON sc.courses_courseid =
tc.courses_courseid
WHERE sc.students_studentid = s.studentid AND
tc.teachers_teacherid = t.teacherid)
在 Oracle 中,您可以使用 minus
,或 SQL 服务器或 PostgreSQL 的 except
集合运算符:(功能等效)
select s.firstname as stud_fname,
s.lastname as stud_lname,
t.firstname as teac_fname,
t.lastname as teac_lname
from students s
cross join teachers t
minus
select s.firstname,
s.lastname,
t.firstname,
t.lastname
from students s
join stu_cou sc
on s.studentid = sc.students_studentid
join courses c
on sc.courses_courseid
join tea_cou tc
on c.courseid = tc.courses_courseid
join teachers t
on tc.teachers_teacherid = t.teacherid
这是一个与@Brian DeMilia 非常相似的解决方案,适用于 MySQL:
SELECT
s.firstname ,
s.lastname ,
t.firstname ,
t.lastname
from
students s
cross join
teachers t
where
(
s.firstname , s.lastname , t.firstname , t.lastname
) NOT IN (
select
s.firstname,
s.lastname ,
t.firstname,
t.lastname
from
students s
inner join stu_cou sc
on s.studentid = sc.students_studentid
inner join courses c
on sc.courses_courseid = c.courseid
inner join tea_cou tc
on c.courseid = tc.courses_courseid
inner join teachers t
on tc.teachers_teacherid = t.teacherid
);
这类似于@Mureinik 的解决方案,但它避免了 CROSS JOIN
:
SELECT s.firstname, s.lastname, t.firstname, t.lastname
FROM students s
JOIN teachers t ON NOT EXISTS (
SELECT *
FROM stu_cou
JOIN tea_cou tc ON sc.courses_courseid = tc.courses_courseid
WHERE sc.students_studentid = s.studentid
AND tc.teachers_teacherid = t.teacherid
);