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
);

测试数据如:

结果会是

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
    );