我不知道如何构建这个问题 - 所以直接把sql语句放在这里。
declare @tbl table(Id varchar(4),Userid varchar(10),Name varchar(max),Course varchar(max))
insert into @tbl values
('1','UserID1','UserA','Physics'),
('2','UserID2','UserB','Chemistry'),
('3,','UserID1','UserA','Chemistry')
现在,
要获得已经使用化学的用户列表,我会写
select * from @tbl where Course='Chemistry'
同样对于物理学,我会写
select * from @tbl where Course='Physics'
问题是当我尝试编写查询“获取未接受物理学的学生列表”时。没有多想,我写了这个
select * from @tbl where Course!='Physics'
它导致了,这是错误的(它正在获取有关UserA的详细信息 - 尽管他已在物理学中注册)
Id Userid Name Course
2 UserID2 UserB Chemistry
3, UserID1 UserA Chemistry
为了解决这个问题,我重新编写了这样的查询 - 不知怎的,我认为这不是正确的方法。
select * from @tbl where Course!='Physics'
and Userid not in (select Userid from @tbl where Course='Physics')
请帮忙!
答案 0 :(得分:1)
尝试以下方法:
SELECT *
FROM @tlb U
WHERE NOT EXISTS (SELECT *
FROM @tbl Inner
WHERE Inner.UserId = U.UserId
AND Course = 'Physics')
有关NOT IN
与EXISTS
的完整讨论,请参阅this question。共识似乎是NOT EXISTS
更可取。
(我注意到你的表定义没有将列标记为NOT NULL
;如果在你的场景中添加它是合适的,那将是一个好主意。)
答案 1 :(得分:1)
如果你想要没有使用物理学的学生列表,那么我建议使用having子句进行聚合:
select userId
from @tbl
group by userId
having sum(case when course = 'Physics' then 1 else 0 end) = 0;
这有明显的优势,即只返回学生ID,而不是学生的多行(当有多个其他课程时)。它也是“set-within-sets”子查询的一个示例,并且比where
版本更容易推广。在缺点方面,not exists
的使用可能能够更好地利用索引。