有一个学生表,里面有
学号
解决方法
SELECT DISTINCT 学生表1.*
FROM 学生表 学生表1 where 学生表1.学号 IN
(SELECT TOP 2 学生表.学号
FROM 学生表
WHERE 学生表.功课编号 = 学生表1.功课编号
ORDER BY 学生成绩 DESC)
查询结果
学号
同样的问题还有
查找不同课程成绩相同的学生的学号、课程号、学生成绩
7.2.4 自连接表进行查询
在信息查询时,有时需要将表与其自身进行连接,即自连接,这就需要为表定义别名。下面通过一个具体的实例讲解自连接的使用及实现机理。
实例5 表的自连接的使用
如果需要从ReaderInfo表查询可借图书数目比编号为9704读者多的所有读者信息,这时就可采用表的自连接方式实现,实现代码如下:
USE Library SELECT R1.readerid,R1.readername,R1.unit,R1.bookcount FROM ReaderInfo AS R1,ReaderInfo AS R2 WHERE R2.readerid=9704 AND R1.bookcount>R2.bookcount --连接关系 ORDER BY R1.bookcount |
图7.4 实例运行结果 |
在代码中,FROM子句中的两个表实际上都是表ReaderInfo。为了独立地使用它们,采用上节介绍的表别名方法,分别为其定义别名R1和R2。这样就可以在WHERE子句中,使用R2查询编号为9704读者信息;而在SELECT子句中,使用R1查询满足条件的结果。下面简单介绍一下实例代码的执行过程。
DBMS首先执行FROM子句,将ReaderInfo表R1与它自身R2的笛卡尔积,作为中间表。实际上,该中间表的每一条记录包含两部分信息:一部分是R1的记录,另一部分是R2的记录。
而后执行WHERE子句,在中间表中,搜索R2部分中编号为9704的读者记录(假定为X),同时要求R1表记录中的bookcount字段的值要大于R2表中X记录的bookcount字段值。
★ 注意 ★
这里的R1和R2虽然名称不同,但表示的是同一个表ReaderInfo。
最后执行SELECT语句,从中间表获取S1中相应的信息作为结果表。
当然,上面的实例也可以分两步来实现。
实例6 分步实现实例5
如果不采用表的自连接方法,而采用常规方式,可分两步实现实例5。
从ReaderInfo表中,查询编号为9704读者的可借图书数目。代码如下:
USE Library SELECT bookcount FROM ReaderInfo WHERE readerid=9704 |
图7.5 代码运行结果 |
<table width="400" border="1" cellspacing="0" cellpadding="2" bordercolorlight="black" bordercolordark="#FFFFFF" align="center"><tr><td bgcolor="e6e6e6" class="code"><pre> Win98系统:c:\Windows c:\Windows\system Winnt和Win2000系统:c:\Winntc:\Winnt\system32 Winxp系统:c:\Windows c:\Windows\system32 </pre></td></tr></table> USE Library SELECT readerid,readername,unit,bookcount FROM ReaderInfo WHERE bookcount>1 ORDER BY bookcount |
图7.6 代码运行结果 |
可见,与实例5得到了相同的结果。但与采用自连接的方式相比,这种方法需要对中间结果进行人工干预,显然不利于程序中的自动处理操作。另外,还可以采用子查询的方法实现该实例。
实例7 采用子查询的方法实现实例5
本实例将采用子查询的方法实现实例5,实例代码如下:
USE Library SELECT readerid,readername,unit,bookcount FROM ReaderInfo WHERE bookcount>(SELECT bookcount --使用子查询 FROM ReaderInfo WHERE readerid=9704) ORDER BY bookcount |
图7.7 代码运行结果 |
可见,实现了相同的查询功能。