SQL 服务器 - 合并两个 select 查询

SQL Server - Combine two select queries

我有两个表,Semester1 和 Semester2。 第 1 学期:

StudentId SubjectId
abc sub1
def sub1
ghi sub1

第 2 学期:

StudentId SubjectId
abc changedSub1
def sub1
ghi changedSub2
newStudent1 sub2
newStudent2 sub3

我正在尝试编写 单个 Select 语句,使其从第 2 学期 selects 有:

  1. 新 StudentIds - 即第 2 学期中不在第 1 学期中的 StudentId。所以这个要求的结果应该是第 2 学期的 newStudent1newStudent2 行。

AND

  1. 更改了 SubjectIds - 即,在第 1 学期和第 2 学期之间,同一 StudentId 的 SubjectId 不同。所以这个要求的结果应该是第 2 学期的 changedSub1changedSub2 行。

我已经能够分别针对 select 2 个要求编写两个单独的查询:

-- Part 1
SELECT * FROM Semester2
    WHERE StudentId NOT IN ( SELECT StudentId from Semester1 );

-- Part 2
SELECT Semester2.StudentId, Semester2.SubjectId 
FROM   Semester2
JOIN Semester1
  ON (Semester1.StudentId = Semester2.StudentId)
  WHERE Semester1.SubjectId <> Semester2.SubjectId;

如何合并这两个查询?或者,如果有一种 better/easier/clearer 方法可以将这两个需求写成一个查询(不合并我的上述查询),我该怎么做?

如果 UNION 不计入“单个查询”,您也可以使用联接在单个查询中执行此操作:

SELECT s2.* 
  FROM Semester2 s2
       LEFT OUTER JOIN Semester1 s1
         ON s2.StudentId = s1.StudentId
         AND s2.SubjectId = s1.SubjectId
 WHERE s1.StudentId IS NULL;

WHERE 子句将使它只显示第 1 学期没有完全匹配的结果。

看起来使用 外连接 的单个查询就足够了

select s2.*
from semester2 s2
left join semester1 s1 on s1.studentId = s2.studentId
where s1.studentId is null or s2.SubjectId != s1.SubjectId;

您可能只需要稍微扩展一下“第 1 部分”查询。现在它排除了第 1 学期的 所有 名学生,但您只想排除第 1 学期没有在第 2 学期更改科目的学生。

像这样:

SELECT * FROM Semester2
WHERE StudentId NOT IN (-- Student ids with same subject from semester 1
                        SELECT StudentId FROM Semester1
                        WHERE Semester1.SubjectId = Semester2.SubjectId);

但是我没有测试过。如果我犯了一些可怕的错误,请告诉我。

一个选项不需要 UNION(这需要扫描 table 两次)并且没有 OR 条件(这可能很慢)并且没有 LEFT JOIN(这混淆优化器认为会有多个连接的行)

SELECT s2.*
FROM semester2 s
WHERE NOT EXISTS (SELECT 1
    FROM semester1 s1
    WHERE s1.studentId = s2.studentId
      AND s2.SubjectId = s1.SubjectId
);

这是我能想到的最简单的事情。

select Semester2.*
    from Semester2
        left outer join Semester1
            on Semester1.StudentId = Semester2.StudentId
    where NULLIF(Semester2.SubjectId,Semester1.SubjectId) is NOT NULL

NULLIF 将 return NULL 如果两者相等(同一学生两个学期的科目相同)。否则它 returns Semester2.SubjectId。这完全排除了您想要排除的内容 - 第 1 学期的学生在第 2 学期没有其他科目。