高级查询技术主要是涉及多个表的链接查询技术、嵌入SELECT语句的子查询技术,把多个查询联合起来的联合技术等。
1. 连接查询
需要同时从两个或者连个以上的表中检索数据。链接就是允许同时从两个表或者两个以上的表中检索数据,指定这些表中的某个或者某些列作为连接条件。在SQL Server中,可以使用两种连接语法的形式,一种是ANSI链接语法形式,这是连接条件出现在FROM子句中;另外一种SQL Server链接语法形式,这是连接条件出现在WHERE条件中。
1. ANSI链接
链接错做可以同时查询两个或者多个表中的数据,所生成的结果集包含多个表中的字段,需要使用连个表中共同拥有的字段以连接多个表。
进行连接操作时,SQL一行一行地比较所指定的字段,然后把比较后的结果和满足条件的数据合并,并生成新的记录。
有三种连接方式:内连接、外连接和交叉连接。在一个SELECT语句中,可以连接多个表;链接通过扩展SELECT语句的FROM字句,增加了两个关键字:JOIN和ON
JOIN:指定要了链接的表
ON:指定这些表共同拥有的字段
在表的主键和外部键的基础上,指定连接条件。
ANSI链接语法形式如下所示:
SELECT table_name.column_name, table_name.column_name,……
FROM { table_name[ join_type] JOIN table_name ON search_conditions}
WHERE[ search_conditions]
其中[ join_type ]可以为如下三个关键字形式:
INNER(内连接):链接查询结果集中仅包含满足条件的行,内连接是SQL Server缺省的连接方式,可以把INNER JOIN简写成 JOIN;
OUTER(外连接):链接查询结果集中既包含哪些满足条件的行,还包含其中某个表的全部行,有三种形式的外连接:左外连接、右外连接、全外连接。
例如:已经选修了4号课程的同学信息的示例,该示例涉及到了学生表和选修课:
SELECT 学生表
FROM 学生表 JOIN 选课表 ON 学生表.学号 选课表.学号
WHERE 选课表 课程号=4
2. SQL Server链接
多表连接,可以在FROM子句后直接指定多个表,语义上表示从这几个表的笛卡尔积中检索数据,可以用WHERE子句设定过滤条件。
SQL Server链接语法形式如下:
SELECT table_name.column_name,table_name.column_name,……
FROM { table_name,table_name,……}
WHERE table_name.column_name join_operator table_name.column_name
在此种语法形式中,FROM子句列出了连接时所使用到的全部表名,WHERE子句指定哪些行应该出现在结果集中,即用WHERE子句设定过滤条件。在WHERE子句中,在两个连接的列中使用链接运算符。
例如:检索出至少已经有一门课程及格的同学的信息示例:
SELECT DISTINCT 学生表 *
FROM 学生表 选课表
WHERE 学生表.学号=选课表.学号 AND 选课表.成绩=60
3. 子查询
子查询是一系列SELECT语句。SELECT语句可以嵌套在其他许多语句中,例如SELECT、INSERT、UPDATE、DELETE等,这些嵌套的SELECT语句就称为子查询。子查询可以把一个复杂的查询分解成一系列的逻辑步骤,这样就可以用一个单个的语句解决一个复杂的查询问题。当一个查询依赖于另一个查询的结果时,子查询会很有用。
使用子查询时,应注意:
子查询要用括号起来
只需要一个值或一系列的值,就可以用子查询代替一个表达式
子查询中不能查询包含数据类型是text或image的字段
子查询中也可以再包含子查询,嵌套可以多至32层
1. 把子查询用作派生的表
可以用子查询产生一个派生的表,用于代替FROM子句中的表。派生表示FROM子句中子查询的一个特殊用法,用一个别名或用户自定义的名字来引用这个派生表。FROM子句中的子查询将返回一个结果集,这个结果集所形成的表将被外层SELECT语句使用。
例如:内层查询用子查询产生了一个派生的表,外层查询将使用内层查询的结果集。在功能上,派生表本身就等同于一个完整的查询
SLECT A *
FROM select 学号,姓名,年龄 from 学生表
Where 班级=‘GZ02计6’ as a
2. 把子查询用作表达式
在T-SQL中,所有使用表达式的地方,都可以用子查询来代替。此时子查询必须返回单个的值或某一个字段的值。子查询可以返回一系列的值来代替出现在WHERE子句中的IN关键字的表达式。
例如:查询GZ02计7班同学的平均年龄以及每个同学年龄与平均年龄的差
SELECT avg(年龄) FROM 学生表 as 平均年龄
其计算结果作为选择列表中的一个输出列,并作为算术表达式的一部分输出:
年龄-(SELECT avg(年龄) FROM 学生表) as 年龄差
3. 相关子查询
相关子查询可被用作动态表达式,这个表达式的值相对于外层查询的每一行而变化。查询处理器为外层查询的每一个记录计算子查询的值,一次一行,而这个子查询每次都会被作为一个表达式而被计算并返回给外层查询。相关子查询是动态执行的子查询和外层查询间的一个非常有效的联合。
使用相关子查询时,内层子查询被反复执行,外层查询有多少记录,内层查询就被齿形多少次。
例如:查询已选修课程号的1且成绩在90分以上的同学的学号及姓名:
SELECT 学号 姓名
FROM 学生表
WHERE 90 <=( SELECT 成绩
FROM 选课表
WHERE 学生表.学号=选课表.学号 AND 课程号=1)
4. 使用EXISTS和NOT EXISTS操作符
在相关子查询中可以使用EXISTS和NOT EXISTS操作符判断某个值是否在一系列的值中。SQL Server处理带有EXISTS和NOT EXISTS操作符的子查询时:
外层查询测试子查询返回的记录是否存在
基于查询所指定的条件,子查询返回TRUE或FALSE
子查询不产生任何数据
例如:同时选修了1号课程和2号课程的同学的信息:
SELECT 学号,姓名,班级
FROM 学生表
WHERE EXISTS(SELECT * FROM 选课表
WHERE 学号=学生表.学号 AND 课程号=1)
AND EXISTS(SELECT * FROM 选课表
WHERE 学号=学生表.学号 AND 课程号=2)
① 找外层表“学生表”的第1行,根据其“学号”值处理内层查询
② 用外层的“学号”与内层表“选课表”的“学号”比较,由此决定外层条件的真、假,如果为真,则此记录为符合条件的结果,反之,则不输出。
③ 顺序处理外层表“学生表”中的第2、3、4、。。。行
检索出每一门选修课都几个的同学信息
SELECT * FROM 学生表 WHERE
NOT EXISTS( SELECT * FROM 选课表
WHERE 学生表.学号=选课表.学号 AND 成绩<60)
AND EXISTS( SELECT * FROM 选课表
WHERE 学生表.学号=选课表.学号)
使用TOP限制结果集
在使用SELECT语句进行查询时,有时我们希望列出前几个结果,而不是全部结果。例如,竞赛时,可能只取成绩最高的前三名,这时就需要使用TOP关键字来选取输出的结果
使用TOP的格式为:
SELECT TOP n[ percent] [with ties] 查询列表
其中:
n:为非负整数
TOP n:表示取查询结果的前n行
TOP n percent:表示取查询结果的前n%行
With ties:表示包括并列的结果
例如:检索出总分在前5位的同学的学号及其总分:
SELECT TOP 5 WITH TIES 学号, SUM(成绩) AS 总分
FROM 选课表
GROUP BY 学号
ORDER BY 总分 DESC
使用TOP时,注意最好与ORDER BY子句一起使用,因为这样的前几名才有意义。但当使用WITH TIES时,要求必须使用ORDER BY子句
合并多个结果集
可以将两个或多个查询的结果组合为一个结果集,这就是合并多个届国际的含义。使用UNION可以实现合并多个查询结果集的目的。作用UNION的格式为:
SELECT 语句1
UNION
SELECT 语句2
UNION [ALL]
……
SELECT 语句n
使用UNION,应注意几点:
在默认情况下,UNION运算符删除全部空余。如果使用ALL选项,那么空余行不删除:
所有查询语句中的列数和列的顺序必须相同
所有查询语句中的对应列的数据类型必须兼容
如果在UNION语句中,包含一个ORDER BY子句,那么整个结果集都要排序
在结果集中,列名来自第1个SELECT子句
例如:对GZ02计6班和GZ02计7班学生的查询结果合并为一个结果集:
SELECT * FROM 学生表 WHERE 班级=‘GZ02计6’
UNION
SELECT * FROM 学生表 WHERE 班级=‘GZ02计7’