用于获取记录的SQL查询

时间:2013-10-17 22:10:04

标签: sql sql-server join

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

请帮忙!

2 个答案:

答案 0 :(得分:1)

尝试以下方法:

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

有关NOT INEXISTS的完整讨论,请参阅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的使用可能能够更好地利用索引。