请教SQL查询语句 学生选课问题

表名:student
字段:id,name
数据如下:
1,学生A
2,学生B

3,学生C

表名:subject
字段:id,name
数据如下:
1,数学
2,物理

3,化学

表名:map_student_subject
字段:studentid, subjectid
数据如下:
1,1
1,2
1,3
2,1
2,2

3,3

现在的问题是查询出同时选择了数学,物理并且没有选择化学的学生姓名。
根据数据,期待的结果应该是:学生B

请问这个Sql应该怎么写啊?
另外我下面的这个写法哪里不对啊?也希望能够一并指出,非常感谢!
[color=blue]select student.name
from
student
join map_student_subject ma
join map_student_subject mb
join map_student_subject mc
on student.id = ma.studentid = mb.studentid = mc.studentid
where
ma.subjectid = '1'
and mb.subjectid = '2'
and mc.subjectid = '3'[/color]
[b]问题补充:[/b]
谢谢大家的热心帮助:>
polymorph大侠的写法是正解,可以得到预期的结果,非常感谢!
另外还想请教一下,如果采用别名的方法,该怎么写这个句子呢?
如果能抽出时间解答的话,不胜感激:D

我的写法最后一句打错字了,不是:
and mc.subjectid = '3'
应该是:
and mc.subjectid <> '3'
但是这样会得到:
学生A
学生A
学生B
学生B
@@

[b]问题补充:[/b]
谢谢energykey的提问:)
xxx=1 and xxx=2 这样肯定是不行的,
所以我想使用别名的方法,
比如我下面这样的写法:
select student.name
from
student
join map_student_subject ma
join map_student_subject mb
on student.id = ma.studentid = mb.studentid
where
ma.subjectid = '1'
and mb.subjectid = '2'
得到的结果是:
学生A
学生B
这个结果是符合预期的(即:同时选择数学物理两个科目同学)
所以给我感觉这样的写法似乎行得通,
但是当我再加上第三个别名表来限定化学的时候,就得不到预期结果了@@
这样的写法真的行不通吗?
[b]问题补充:[/b]
TO energykey:
这样的写法:
select name from student where id=
(select ma.studentid from map_student_subject ma where ma.subjectid=1 and studentid in
(select ma.studentid from map_student_subject ma where ma.subjectid=2 and ma.subjectid<>3)
)
会报错,
我看了一下子查询,会返回:学生A,学生B两个结果。
是不是什么地方笔误了?

[b]问题补充:[/b]
pengjiu大侠的方法也是正解,非常的感谢:D
分数我就平分给提供了可以得到预期答案的两位,再次感谢!!
同时向每一位热心的提供解答的大侠们致谢:D

[code="sql"]
SELECT STUDENTNAME
FROM (SELECT STUDENTID,
SUM(CASE WHEN SUBJECTID = 1 THEN 1 ELSE 0 END) MATH,
SUM(CASE WHEN SUBJECTID = 2 THEN 1 ELSE 0 END) PHYSICS,
SUM(CASE WHEN SUBJECTID = 3 THEN 1 ELSE 0 END) CHEMISTRY
FROM MAP_STUDENT_SUBJECT
GROUP BY STUDENTID) A
JOIN STUDENT B ON (A.STUDENTID = B.STUDENTID)
WHERE A.MATH > 0
AND A.PHYSICS > 0
AND A.CHEMISTRY = 0
[/code]

试一下这个吧select mss_.studentid as func1_4_ from map_student_subject mss_ inner join subject sys_ on mss_.subjectid=sys_.subjectid where sys_.subjectid='1' and sys_.subjectid='2'

呵呵,你这个问题有意思,我想了一下,,,下班了,明天继续想~回家烧饭了。

:lol: :cry:

vdsgrs s g rsggg

[code="sql"]select student.name
from
student
join map_student_subject ma
join map_student_subject mb
join map_student_subject mc
on student.id = ma.studentid = mb.studentid = mc.studentid
where
ma.subjectid = '1'
and mb.subjectid = '2'
and mc.subjectid = '3'[/code]

这是语法问题,join后面必须紧跟上on语句。

[code="java"]
select s.name from student s where s.id=
(select m.studentid map_student_subject
m,subject sb where m.subjectid = sb.id and m.name in('数学','物理'));
[/code]

1楼强悍啊,,,呵呵,好久没写SQL了,,,这种写法以前确实还没写过,主要是业务上没遇到过这样的需求。。。 :lol:

楼主还在问什么?

你这个问题的难点在于“同时选择”,这个同时在一行SQL里就难了,因为不可能同时xxx=1 and xxx=2这样肯定是没有结果的,我觉得只有通过子查询,而且需要临时表。

光光join无法实现“交集”效果。

我想了条更简单的方法

其实子查询的结果本身就是一张临时表,所以要求交集只需要两次子查询即可!

代码如下
[code="java"]
select name from student where id=
(select ma.studentid from map_student_subject ma where ma.subjectid=1 and ma.subjectid<>3 and studentid in
(select ma.studentid from map_student_subject ma where ma.subjectid=2 and ma.subjectid<>3)
)
[/code]

[quote]
select name from student where id=
(select ma.studentid from map_student_subject ma where ma.subjectid=1 and ma.subjectid<>3 and studentid in
(select ma.studentid from map_student_subject ma where ma.subjectid=2 and ma.subjectid<>3)
)
[/quote]

[code="sql"] select student.id,student.name,s.id '数',l.id '理',h.id '化' from

student student

left join
map_student_subject s on student.id=s.studentid and s.subjectid=1

left join
map_student_subject l on student.id=l.studentid and l.subjectid=2

left join

map_student_subject h on student.id=h.studentid and h.subjectid=3

where isnull(h.id)=1 or length(h.id)<0[/code]

条件你可以自己组合。

上面的第二次查询的时候ma.subjectid<>3是多于的,因为第一个子查询已经将选了3的人排除在外了。

所以:

[quote]select name from student where id=
(select ma.studentid from map_student_subject ma where ma.subjectid=1 and studentid in
(select ma.studentid from map_student_subject ma where ma.subjectid=2 and ma.subjectid<>3)
)
[/quote]
即可。

第一次查询where ma.subjectid=2 and ma.subjectid<>3,查出选了物理并且没有选化学的人,作用如下:
1.排除了选化学的人。
2.查出了选了物理的人。

假设这个结果集为A,
那么只要从A中再查询选了数学的人,就相当于执行了一次交集。

这个方法的关键点是第二次子查询以studentid作为条件。