一个SQL问题,求解释

specialco 2014-10-12 11:41:24
1.已知SQL关系模式

s(s#,sname)
c(c#,cname)
sc(s#,c#,score)

create table s( s# varchar (10), sname varchar (10));
go
create table c( c# varchar (10), cname varchar (10));
go
create table sc( s# varchar (10), c# varchar(10 ),score varchar(10 ));
go

insert into s values ('s1' ,'sa');
insert into s values ('s2' ,'sb');
insert into s values ('s3' ,'sc');
insert into s values ('s4' ,'sd');

insert into c values ('c1' ,'ca');
insert into c values ('c2' ,'cb');
insert into c values ('c3' ,'cc');
insert into c values ('c4' ,'cd');

insert into sc values ('s1' ,'c2', '50');
insert into sc values ('s1' ,'c4', '50');
insert into sc values ('s2' ,'c1', '60');
insert into sc values ('s2' ,'c2', '70');
insert into sc values ('s3' ,'c1', '80');
insert into sc values ('s3' ,'c3', '90');
insert into sc values ('s4' ,'c1', '80');
insert into sc values ('s4' ,'c2', '90');
insert into sc values ('s4' ,'c3', '90');
insert into sc values ('s4' ,'c4', '90');

问题: 找出至少包含了S2选修了课程的学员

答案:

select *
from sc a
where not exists ( select *
from SC
where not exists ( select *
from SC C
where sc . c# = C. c#
and a . s# = c. s# )
and SC . s# = 'S2'
)

答案是有了,不过很难理解各种逻辑,求大神解释。
...全文
269 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
还在加载中灬 2014-10-13
  • 打赏
  • 举报
回复
我感觉差不多吧 EXISTS的逻辑上处理是一条一条去判断的,
specialco 2014-10-13
  • 打赏
  • 举报
回复
select *   from SC
                                where   not exists ( select *
                                  from SC C
                                 where sc . c# = C. c#
                                   and 'S1'= c. s# )
这部分代码 的意思:选出 所有选修了 S1 学员未选修 的课程 例如: S2 C1 S3 C1 S3 C3 S4 C1 S4 C3 =================================================================
select *   from SC
                                where   not exists ( select *
                                            from SC C
                                            where sc . c# = C. c#
                                             and 'S1'= c. s# )
                                and SC.S# =‘S2'
这部分代码意思是: 选出 S2学员 选修了 S1 学员未选修 的课程 例如:S2 C1 ========================================================================
select *
from sc a
where not exists ( select *
                                from SC
                                where   not exists ( select *
                                                                from SC C
                                                                 where sc . c# = C. c#
                                                                   and a . s# = c. s# )
                                   and SC . s# = 'S2'
)
第三部分代码的是意思其实就一条一条记录去判断是否符合要求: 如果存在 S2学员选修了课程而该学员没选修,就剔除。 不知道 这样解释,大神们看看是否可以?
还在加载中灬 2014-10-13
  • 打赏
  • 举报
回复

WITH CTE AS(
	SELECT C# FROM SC WHERE sc . s# = 'S2'
)
,CTE2 AS(
	SELECT S#,C# FROM s,cte
)
,CTE3 AS(
	SELECT A.S# FROM CTE2 A LEFT JOIN SC B ON A.C#=B.C# AND A.S#=B.S# WHERE B.S# IS NULL GROUP BY A.S#
)
SELECT A.* FROM SC A LEFT JOIN CTE3 B ON A.S#=B.S# WHERE B.S# IS NULL
还在加载中灬 2014-10-13
  • 打赏
  • 举报
回复
引用 5 楼 specialco 的回复:
感觉逻辑本身就点绕,不知道有没有更好的解决方案。
我还真尝试了其他解决方案,一个EXISTS都没有,不过,感觉更绕~~ 像这种范围的东西,感觉没有比EXISTS更好描述的SQL了~~
xiaodongni 2014-10-13
  • 打赏
  • 举报
回复
突然发现 原来这个一个经典问题。 针对这个有各种解释。这里面可以不用SC表3次。还有S,C表就OK 了。 你看看这个链接 http://wenku.baidu.com/link?url=BK8Yu_QrvPVhcRFUmUYyFr1qiqRCZ2tFgHstQriCY0VXm4DXRR1uSuOjOO_LsPkfdJU6OwlugB3Rud7wdWX0aOqtMf0k7F5R6IXOTLPG31u 里面有各种解释。
xiaodongni 2014-10-13
  • 打赏
  • 举报
回复
引用 5 楼 specialco 的回复:
[quote=引用 4 楼 ky_min 的回复:] 有点绕,但是可以分段理解, 我们先把第一个括号里面的东西拿出来
select *
                                from SC
                                where   not exists ( select *
                                                                from SC C
                                                                 where sc . c# = C. c#
                                                                   and a . s# = c. s# )
                                   and SC . s# = 'S2'
这里面别名a,也就是最外面的表,只带入了s#,也就是sc的所有学生,我们先取第一条记录的学生's1',带入理解,即成了
select *
                                from SC
                                where   not exists ( select *
                                                                from SC C
                                                                 where sc . c# = C. c#
                                                                   and 's1' = c. s# )
                                   and SC . s# = 'S2'
而这句,很明显的意思是,查询所有在学生s2的课程中,没有学生s1也在学习的课程 如果这个查询有值,那么,这个查询的not exists不成立,那最外面的别名为a的第一记录的学生's1'不成立 因此整体语句的意思即是 在别名a的表中的所有学生里,不存在( 学生S2有学的课程,而他(别名a的学生)没有学习的课程) 不知这样有没有说清楚~~
感觉逻辑本身就点绕,不知道有没有更好的解决方案。[/quote]
SELECT * FROM SC 
WHERE S# in(select S# from 
(SELECT S#,COUNT(S#) as counts FROM (select S# from sc as a 
where c# IN
(SELECT C# FROM Sc WHERE S#='S2')) as p
group by S#) as t
where t.counts=(select count(C#) from Sc where S#='S2'))
我看了性能还差一点,大概是我的57%,你的43%,这个好理解一点。 先找出所有学习了S2学习的课程。然后算出各个学生的学习了S2学习的课程的数量。 如果这个数量等于S2学习的课程数量(这里就是2)那么他肯定满足条件。如果小于肯定不满足。
AcHerat 元老 2014-10-13
  • 打赏
  • 举报
回复
我们这么理解下,这个查询用到了三个SC,自身的表连接查询。 1、SC a 2、SC 3、SC C 可以将 第一个SC看做是取 S#,即学生 第二个SC看做是取 C#,即课程,而且是S2选修的课程 第三个SC里,可以看到两个条件,课程对应第二个SC的课程,就是S2选修的课程,在数据里反应是 C1 C2,到这里看第二个条件就很容易理解了,如果对于C1 C2两个课程,不存在该学生选修的话就排除掉,只有两个课程在该学生的选修课里都存在的时候查询出来。
xiaodongni 2014-10-13
  • 打赏
  • 举报
回复
引用 3 楼 specialco 的回复:
[quote=引用 2 楼 alimake 的回复:] 结果贴出来,感觉这两个not exisis是多余的
还请大神明示[/quote] 我前面看错了。这个我看了半天也没看懂。2层的相关子查询。
specialco 2014-10-13
  • 打赏
  • 举报
回复
引用 4 楼 ky_min 的回复:
有点绕,但是可以分段理解, 我们先把第一个括号里面的东西拿出来
select *
                                from SC
                                where   not exists ( select *
                                                                from SC C
                                                                 where sc . c# = C. c#
                                                                   and a . s# = c. s# )
                                   and SC . s# = 'S2'
这里面别名a,也就是最外面的表,只带入了s#,也就是sc的所有学生,我们先取第一条记录的学生's1',带入理解,即成了
select *
                                from SC
                                where   not exists ( select *
                                                                from SC C
                                                                 where sc . c# = C. c#
                                                                   and 's1' = c. s# )
                                   and SC . s# = 'S2'
而这句,很明显的意思是,查询所有在学生s2的课程中,没有学生s1也在学习的课程 如果这个查询有值,那么,这个查询的not exists不成立,那最外面的别名为a的第一记录的学生's1'不成立 因此整体语句的意思即是 在别名a的表中的所有学生里,不存在( 学生S2有学的课程,而他(别名a的学生)没有学习的课程) 不知这样有没有说清楚~~
感觉逻辑本身就点绕,不知道有没有更好的解决方案。
还在加载中灬 2014-10-13
  • 打赏
  • 举报
回复
有点绕,但是可以分段理解, 我们先把第一个括号里面的东西拿出来
select *
                                from SC
                                where   not exists ( select *
                                                                from SC C
                                                                 where sc . c# = C. c#
                                                                   and a . s# = c. s# )
                                   and SC . s# = 'S2'
这里面别名a,也就是最外面的表,只带入了s#,也就是sc的所有学生,我们先取第一条记录的学生's1',带入理解,即成了
select *
                                from SC
                                where   not exists ( select *
                                                                from SC C
                                                                 where sc . c# = C. c#
                                                                   and 's1' = c. s# )
                                   and SC . s# = 'S2'
而这句,很明显的意思是,查询所有在学生s2的课程中,没有学生s1也在学习的课程 如果这个查询有值,那么,这个查询的not exists不成立,那最外面的别名为a的第一记录的学生's1'不成立 因此整体语句的意思即是 在别名a的表中的所有学生里,不存在( 学生S2有学的课程,而他(别名a的学生)没有学习的课程) 不知这样有没有说清楚~~
specialco 2014-10-13
  • 打赏
  • 举报
回复
引用 2 楼 alimake 的回复:
结果贴出来,感觉这两个not exisis是多余的
还请大神明示
xiaodongni 2014-10-13
  • 打赏
  • 举报
回复
结果贴出来,感觉这两个not exisis是多余的
xiaodongni 2014-10-13
  • 打赏
  • 举报
回复
结果贴出来,感觉这两个not exisis是多余的

34,590

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧