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 行有:
- 新 StudentIds - 即第 2 学期中不在第 1 学期中的 StudentId。所以这个要求的结果应该是第 2 学期的
newStudent1
和 newStudent2
行。
AND
- 更改了 SubjectIds - 即,在第 1 学期和第 2 学期之间,同一 StudentId 的 SubjectId 不同。所以这个要求的结果应该是第 2 学期的
changedSub1
和 changedSub2
行。
我已经能够分别针对 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 学期没有其他科目。
我有两个表,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 行有:
- 新 StudentIds - 即第 2 学期中不在第 1 学期中的 StudentId。所以这个要求的结果应该是第 2 学期的
newStudent1
和newStudent2
行。
AND
- 更改了 SubjectIds - 即,在第 1 学期和第 2 学期之间,同一 StudentId 的 SubjectId 不同。所以这个要求的结果应该是第 2 学期的
changedSub1
和changedSub2
行。
我已经能够分别针对 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 学期没有其他科目。