SQL - 选择对每个科目都有考试的学生

时间:2015-01-31 14:34:55

标签: sql select

我有两张桌子: 考试(StudentID,SubjectID), 受试者(SubjectID)

并希望选择对所有科目进行考试的学生。怎么做? 是否可以不使用GROUP和COUNT?

2 个答案:

答案 0 :(得分:2)

你可以通过多种方式实现这一目标。其中之一:

DECLARE @students TABLE ( id INT )
DECLARE @exams TABLE ( id INT )
DECLARE @studentexams TABLE
    (
      studentid INT ,
      examid INT
    )

INSERT  INTO @exams
VALUES  ( 1 ),
        ( 2 )
INSERT  INTO @students
VALUES  ( 1 ),
        ( 2 ),
        ( 3 )
INSERT  INTO @studentexams
VALUES  ( 1, 1 ),
        ( 1, 2 ),
        ( 2, 1 )


SELECT  *
FROM    @students s
WHERE   NOT EXISTS ( SELECT *
                     FROM   @exams e
                     WHERE  e.id NOT IN ( SELECT    se.examid
                                          FROM      @studentexams se
                                          WHERE     se.studentid = s.id ) )

输出:

id
1

答案 1 :(得分:1)

这是你之后的事情:

--list all students
select * 
from @students st
--where there isn't
where not exists
(
--any subject
    select top 1 1 
    from @subjects su 
--for which that student did not take an exam
    where su.id not in 
    (
        select subjectid 
        from @exams e 
        where studentId = st.id
    )
)

这里是完整的代码(即包括样本数据表):

declare @subjects table(id bigint not null identity(1,1), title nvarchar(32))
declare @students table(id bigint not null identity(1,1), name nvarchar(32))
declare @exams table(id bigint not null identity(1,1), studentId bigint, subjectId bigint, grade nchar(1), attempt int)


insert @subjects select 'Maths' union select 'English' union select 'Geography' union select 'Computer Science'
insert @students select 'Anna' union select 'Billy' union select 'Christie' union select 'Daniel'
insert @exams select st.Id, su.Id, grade, attempt
from
(
    select 'Anna' student, 'Maths' subject, 'A' grade, 1 attempt
    union select 'Anna' student, 'English' subject, 'A' grade, 1 attempt
    union select 'Anna' student, 'Geography' subject, 'A' grade, 1 attempt
    union select 'Anna' student, 'Computer Science' subject, 'A' grade, 1 attempt
    union select 'Billy' student, 'Maths' subject, 'A' grade, 1 attempt
    union select 'Billy' student, 'Computer Science' subject, 'A' grade, 1 attempt
    union select 'Christie' student, 'Maths' subject, 'A' grade, 1 attempt
    union select 'Christie' student, 'English' subject, 'F' grade, 1 attempt
    union select 'Christie' student, 'English' subject, 'E' grade, 2 attempt
    union select 'Christie' student, 'English' subject, 'A' grade, 3 attempt
    union select 'Daniel' student, 'Maths' subject, 'A' grade, 1 attempt
    union select 'Daniel' student, 'English' subject, 'A' grade, 1 attempt
    union select 'Daniel' student, 'Geography' subject, 'A' grade, 1 attempt
    union select 'Daniel' student, 'Computer Science' subject, 'F' grade, 1 attempt
    union select 'Daniel' student, 'Computer Science' subject, 'A' grade, 2 attempt
) x
inner join @students st on st.name = x.student
inner join @subjects su on su.title = x.subject

--list all students
select * 
from @students st
--where there isn't
where not exists
(
--any subject
    select top 1 1 
    from @subjects su 
--for which that student did not take an exam
    where su.id not in 
    (
        select subjectid 
        from @exams e 
        where studentId = st.id
    )
)