1

我不知道如何框定这个问题——所以直接把 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')

请帮忙!

4

2 回答 2

1

如果您想要没有上过物理的学生列表,那么我建议使用 have 子句进行汇总:

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可能能够更好地利用索引。

于 2013-10-17T22:47:11.613 回答
1

尝试以下操作:

SELECT *
       FROM @tlb U
       WHERE NOT EXISTS (SELECT  *
                                 FROM @tbl Inner
                                 WHERE Inner.UserId = U.UserId
                                 AND Course = 'Physics')

有关NOT INvs的完整讨论EXISTS,请参阅此问题。共识似乎NOT EXISTS是更可取的。

(我注意到您的表定义没有将列标记为NOT NULL;如果在您的场景中添加它是合适的,那将是一个好主意。)

于 2013-10-17T22:13:12.707 回答