用于检索不相关记录的元组的SQL

时间:2015-10-04 16:07:06

标签: sql select cross-join

想象一下像这样的数据库:

test database

寻找所有学生 - 不分享任何课程的老师。结果应为(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教授CS和MATH课程;
  • 学生A进入CS课程;
  • 学生B参加文学和体育课程;

结果将是

STUDENT B - TEACHER A

寻找通用的解决方案,这就是没有特定数据库说明的原因。

4 个答案:

答案 0 :(得分:3)

在Oracle中,您可以使用minus,或SQL Server或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

答案 1 :(得分:2)

您可以从交叉联接开始,然后删除任何具有关系的对:

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)

答案 2 :(得分:1)

这与@ Mureinik的解决方案类似,但它避免了<select id="customer-dd" ng-model="selectedCustomer"> <option value="">select...</option> <option ng-if="code == 'multiAdmin' || code == 'admin' " ng-repeat="companyCode in companyGroups track by $index" value="{{ companyCode }} " >{{ companyCode }}</option> <option ng-if="code != 'multiAdmin' || code != 'admin' " ng-repeat="company in code track by $index" value="{{ company }} " >{{ company }}</option> </select>

CROSS JOIN

答案 3 :(得分:0)

这是一个非常类似于@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 
        );