6_2数据查询
还是使用6_1里面创建的数据哦
use EMIS
go
--连接查询
--一个查询同时涉及两个以上的表,就是连接查询
--分类:交叉连接查询、内连接查询、外连接查询
--多个表连接,需要利用连接条件来指定各列之间进行连接的关系。连接条件中的列必须具有已知的数据类型才能正确连接
--交叉连接(非限制连接)
--两个表中的记录的交叉乘积,结果集中的列为两个表属性列的和,其连接的结果会产生一些毫无疑义的记录,而且操作很耗时,该运算的实际意义不大
--select 列明 from 表名1 cross jion 表名2
--交叉示意图
--学生与班级连接
select 学号,姓名,性别,学生.班级代码,出生日期,班级.班级代码,班级.班级名称
from 学生 cross join 班级
--内连接
--简单连接,将两个或多个表进行连接,只出现相匹配的记录,不匹配的纪录将无法查询出来
--分类:等值连接(自然连接)、非等值连接、自连接
--等值连接
--连接条件是在where子句中给出的,只有满足连接条件的性才会出现在程序结果中
--select 列表列名 from 表名1 [inner] join 表名2 on 表名1.列名=表名2.列名
--或select 列表列名 from 表名1,表名2 where 表名1.列名=表名2.列名
--内连接示意图
--查询每个学生所在班级名称
select 学号,姓名,性别,学生.班级代码,班级.班级代码,班级.班级名称
from 学生 inner join 班级 on 学生.班级代码=班级.班级代码
--自然连接
--在等值连接中,把目标列中重复的属性去掉,成为自然连接
select 学号,姓名,性别,学生.班级代码,班级.班级名称
from 学生 inner join 班级 on 学生.班级代码=班级.班级代码
--非等值连接
--当连接条件中的关系运算符实用除‘=’以外的其他关系运算符时,这样的内连接称为非等值连接(很少用到)
--自连接
--一个表与其自身进行连接称为表的自连接
--查询与李冬冬同一个专业的教师信息
select Y.教师编号,Y.姓名,Y.专业
from 教师 X,教师 Y
where X.专业=Y.专业 and X.姓名='李冬冬' and Y.姓名!='李冬冬'
--Y X表的别名
--外连接
--指连接关键字join的后面表找那个指定列连接在前一个表中指定列的左边或右边,如果两个表中的指定列都没有匹配的行则返回空值
--左外连接 left outer join(左全部输出)
--右外连接 right outer join(右全部输出)
--全外连接 full outer join(左右全部输出)
--outer可以省略不写
--外连接示意图
--左外连接实例
--查询学生选课信息,包括没有选课的学生信息
select 学生.学号,学生.姓名,选课.课程号
from 学生 left join 选课
on 学生.学号=选课.学号
--右外连接实例
--查询被选修的课程信息,没有被选的课程可也输出
select 学号,选课.课程号,课程名,选课.成绩 from 选课 right join 课程
on 选课.课程号=课程.课程号
--全外连接
select 学号,选课.课程号,课程名,选课.成绩 from 选课 full join 课程
on 选课.课程号=课程.课程号
--嵌套查询
--将一个查询语句嵌套在另一个查询语句的where子句或having短语的条件中的查询称为嵌套查询
--在SELECT查询语句中,子查询也称为嵌套查询,是一个嵌套在 SELECT中的查询语句。处于内层的查询称为子查询,处于外层的查询称为父查询。
--任何允许使用表达式的地方都可以使用子查询。T-SQL语句支持子查询,正是SQL结构化的具体体现。
--子查询SELECT语句必须放在括号中,子查询叧返回一行数据,并且返回的数据常常也叧有一列
--可以用子查询来检查或者设置变量和列的值,或者用子查询来测试数据行是否存在于WHERE子句中。
--注意: ORDER BY子句叧能对最终查询结果排序,即在子查询中的SELECT语句中不能使用ORDER BY子句。
--带有IN谓词的子查询
--IN谓词用于判断一个给定值是否在子查询结果集中。当父查询表达式与子查询的结果集中的某个值相等时,返回TURE,否
--则返回FALSE。同时,可以在IN关键字之前使用NOT,表示表达式的值不在查询结果集中
--查询至少有一门课程不及格的学生的信息
select 学生.姓名,姓名,班级代码 from 学生
where 学号 in(select 学号 from 选课 where 成绩<60)
--带有比较运算符的子查询
--查询名叫‘王庆子’的学生的选课信息
select * from 选课 where 学号=(select 学号 from 学生 where 姓名='王庆子')
--查询与李冬冬同一专业的教师信息,不包括李冬冬
select * from 教师 where 专业=(select 专业 from 教师 where 姓名='李冬冬') and 姓名!='李冬冬'
-- 带有ANY、SOME或ALL关键字的子查询
--ALL代表所有值,ALL指定的表达式要与子查询结果集中的每个值都迚行比较,当表达式与每个值都满足比较的关系时,才返回TRUE,否则返回FALSE。
--SOME或ANY代表某些或者某个值,表达式叧要与子查询结果集中的某个值满足比较的关系时,就返回TRUE,否则返回FALSE
--查询成绩比王庆子同学高得学生选课信息
select * from 选课 where 成绩>any(select 成绩 from 选课 where 学号=(select 学号 from 学生 where 姓名='王庆子'))--any
select * from 选课
where 成绩>some(select 成绩 from 选课
where 学号=(select 学号 from 学生
where 姓名='王庆子'))
select *
from 选课
where 成绩>all(select 成绩
from 选课
where 学号=(select 学号
from 学生
where 姓名='王庆子'))
-- 带有EXISTS谓词的子查询
--EXISTS称为存在量词,WHERE子句中使用EXISTS表示当子查询的结果非空时,条件为TRUE,反之则为FALSE。
--EXISTS前面也可以加NOT,表示检测条件为“不存在”,使用存在量词NOT EXISTS后,若内层查询结果为空,则外层的WHERE子句返回真值,否则返回假值。
--EXISTS语句与IN非常类似,它们都根据来自子查询的数据子集测试列的值。不同之处在于,EXISTS使用联接将列的值与子查询中的列联接起来,而IN不需要联接,它直接根据一组以逗号分隔的值迚行比较。
--查询没有选修课程号为‘0001’
select * from 学生
where not exists (select *
from 选课
where 学号=学生.学号 and 课程号='0001')
--查询李冬冬同专业的教师,不含李冬冬
select * from 教师 x where exists (select * from 教师 y
where x.专业=y.专业 and y.姓名='李冬冬') and x.姓名!='李冬冬'
--查询选修了全部课程的学生学号和姓名
--即不存在一门课程,所求学生没有选择它
select 学号 ,姓名 from 学生
where not exists (select * from 课程
where not exists(select * from 选课
where 学号=学生.学号 and 课程号=课程.课程号))
--联合查询
--把多个查询的结果进行集合运算
--union 并
--union并,参与并运算操作的两个查询语句,其结果的列数必须相同,对于项的数据类型也必须相同
--查询班级名称为'15级网络技术301班'的女生和班级名为'17级网络技术301班'的男生信息
select * from 学生 where 性别='女' and 班级代码=(select 班级代码 from 班级 where 班级名称='15级网络技术301班')
union
select * from 学生 where 性别='男' and 班级代码=(select 班级代码 from 班级 where 班级名称='17级网络技术301班')
--intersect 交操作符返回两个查询检索出的共有行,即左右查询中都出现的记录
--查询选修了分别含'政策'和'架构'两个字的课程的学生名单
select 姓名
from 学生,选课,课程
where 学生.学号=选课.学号 and 选课.课程号=课程.课程号 and 课程名 like '%政策%'
intersect
select 姓名
from 学生,选课,课程
where 学生.学号=选课.学号 and 选课.课程号=课程.课程号 and 课程名 like '%架构%'
--except操作符返回将第二个查询检索出的行从第一个查询检索出的行中减去之后剩余的行
--查询选修了高等数学课,却没有选修'专业英语'的学生姓名
select distinct 姓名
from 学生,选课,课程
where 学生.学号=选课.学号 and 选课.课程号=课程.课程号 and 课程名='高等数学'
except
select 姓名
from 学生,选课,课程
where 学生.学号=选课.学号 and 选课.课程号=课程.课程号 and 课程名='专业英语'
--排序函数
--– ROW_NUMBER函数、 – RANK函数 – DENSE_RANK()函数 – NTILE()函数
--ROW_NUMBER()函数返回结果集分区内行的***,每个分区的第一行从1开始,返回类型为bigint
--语法格式如下:• ROW_NUMBER() OVER([ PARTITION BY value_expression , ... [ n ] ] order_by_clause )
select ROW_NUMBER() over (partition by 性别 order by 出生日期) as 年龄序号,姓名,性别,出生日期 from 学生
--BANK()函数返回结果集的分区内每行的排名。RANK()函数并不总返回连续整数。行的排名是相关行之前的排名数加一。 返回类型为bigint
--语法格式如下:• RANK ( ) OVER ( [ partition_by_clause ] order_by_clause )
--其中,partition_by_clause为将FROM子句生成的结果集划分为要应用RANK()函数的分区;order_by_clause为确定将RANK值应用于分区中的行时所基于的顺序。
--安参加工作的时间对教师记录进行排序
select RANK() OVER (ORDER BY 工作时间) AS 参建工作时间,姓名,工作时间 from 教师
--DENSE_RANK()函数返回结果集分区中行的排名,在排名中没有任何间断。行的排名等于所讨论行之前的所有排名数加一。 返回类型为bigint
--语法格式如下:
-- DENSE_RANK ( ) OVER ( [ <partition_by_clause> ] < order_by_clause > )
--• 其中,<partition_by_clause>将 FROM 子句生成的结果集划分为多个应用 DENSE_RANK函数的分区;<order_by_clause>确定将DENSE_RANK 函数应用于分区中各行的顺序。
--安参加工作的时间对教师记录进行排序,排序号连续
select DENSE_RANK() OVER (ORDER BY 工作时间) AS 参加工作先后 ,姓名,工作时间 from 教师
--NTILE()函数将有序(数据行)分区中的数据行分散到指定数目的组中。这些组有编号,编号从1开始。对于每一个数据行,NTILE将返回此数据行所属的组的编号。返回类型为bigint
--NTILE的Transact-SQL语法约定如下: NTILE (integer_expression) OVER ( [ <partition_by_clause> ] < order_by_clause > )
--参数的含义如下:
--(1)integer_expression:一个正整数常量表达式,用于指定每个分区必须被划分成的组数。 integer_expression 的类型可以是int或bigint。
--(2)<partition_by_clause>: 将FROM子句生成的结果集划分成此函数适用的分区。 (3)<order_by_clause>:确定NTILE值分配到分区中各行的顺序。当在排名函数中使用<order_by_clause> 时,不能用整数表示列
--把教师按照工作时间分为四组
select NTILE(4) OVER (ORDER BY 工作时间) AS 参建工作先后组,姓名,工作时间 from 教师
--动态查询
--动态查询:根据实际需要临时组装成的SQL语句。
--动态语句可以有完整的SQL语句组成,也可以根据操作分类,分别指定SELECT或INSERT等关键字,同时也可以指定查询对象和查询条件。
--动态SQL语句是在运行时有程序创建的字符串,他们必须是有效的SQL语句。
declare @cname char(20)
set @cname='李冬冬'
select * from 教师 where 姓名[email protected]
--exec 执行SQL
--普通SQL语句可以用Exec执行。例如下面的代码:
--普通的SQL语句
SELECT * FROM 课程
--利用EXEC执行SQL语句
EXEC('SELECT * FROM 课程')
--使用扩展存储过程执行SQL语句
EXEC sp_executesql N'SELECT * FROM 课程'
declare @cnam varchar(20)
set @cnam='课程名'
--select @cname from 课程
exec('select '[email protected]+' from 课程')