SQL server 数据查询

文章目录


前言

本文简单总结下数据查询语句,自己复习看书时候写的

基础语法

单行注释:--

多行注释/* … */

一、单表查询

1. 选择表中的若干列

--查询指定列
select sno, sname
from student;

--查询全部列
select *
from student;

--查询经过计算的值
select sname, 2014-sage
from student;

--设置别名
select sname NAME, sage AGE
from student;

2. 选择表中的若干元组

--消除重复的行(仅仅是不显示,并非删除)
select distinct sno
from sc;

--查询满足条件的元组
select sname
from student
where sdept='cs';

这里讲下执行查询的一种可能过程:
对表进行全表扫描,取出一个元组,检查是否满足条件。满足,取出sname列的值,形成新的元组输出。不满足,取下一个元组。

为什么说这是可能过程呢,因为具体的操作可能会根据优化器优化,利用索引或者根据某些规则来作出选择,进行优化。

具体sql如何执行查询操作可以参考下面两篇文章:
SQL查询操作处理流程
一条select的查询的过程

--between
select sname
from student
where sage between 20 and 30
--同样也有not between, 左右可取

--确定集合
select name
from student
where sdept in('cs','ma','is');
--in 和 not in可以用来查找属性值属于指定集合的 元组,即本质是选取了几个符合指定的元组

--字符匹配
select sname
from student
where sno like '001';

select sname
from student
where sno like '陈%';
--  %是通配符(长度可以为0)
--  _是任意单个字符

--换码字符
--查询DB_Design课程的课程号
select cno
from course
where cname like 'DB\_Design' escape '\';

--空值查询
select sno, cno
from sc
where grade is null;
--注意,不能用=替换

--多重条件查询
--用and 或 or, 其实in就是多个or的缩写

3. order by 字句

对查询结果进行排序。ASC升序或DESC降序

select sno, grade
from sc
where sno='3'
order by grade desc;

4. 聚集函数

count, sum, avg, max, min

--查询选修了课程的学生人数
select count(distinct sno)
from sc;

--查询1号学生的平均成绩
select avg(grade)
from sc
where cno='1';

聚集函数处理会自动跳过空值
聚集函数只能用在select字句和group by中的having字句

5. group by 子句

--球每个课程号及相应的人数
select cno, count(sno)
from sc
group by cno;

--查询选修了三门以上课程的学生学号
select sno
from sc
group by sno
having count(*)>3;

二、连接查询

1. 等值与非等值连接查询

where中的表达式将成为两个表的连接条件

select student.*,sc.*
from student, sc
where student.sno=sc.sno;
--形成新的元组

--自然连接,即没有重复的属性列

2. 自身连接

其实就是给相同的表取个别名

select first.cno, second.cpno
from course first, course second
where first.cpno=second.cno;

3. 外连接

意思我觉得有点像是全连接,就是在上述连接中,若没有成功连接上的元组(不满足where里的限定)就会被舍弃,不显示。外连接将会把两个表中的所有元组都显示出来,如果有元组没有满足where限定,还是会被显示出来,而没有被匹配到的另外半边就会用null来填充。
所以又分为左外连接和右外连接,如果是做外连接就会显示左边关系中的所有元组。

select *
from student left out join sc on(student.sno=sc.sno);
--用on来限定
--也可以用using去掉重复结果,from student left out  join sc using (sno);

4. 多表连接

就是两个表以上的连接
和两个表没啥区别

三、 嵌套查询

重点
select-from-where被称为一个查询块

1.带有in谓词的子查询

其实思想就是一个分步骤的查询。
查询与xx在同一个系学习的学生
先查询xx所在的系,结果为’CS‘,在查询限定专业等于cs的同学

select sno, sname, sdept
from student
where sdept in(
	select sdept
	from student
	where sname='xx');

值得一提的是,这个查询过程是不唯一的。一种是向外处理,先执行了子查询,在用结果去执行父查询。也可能是一种自身连接。所以实现查询请求可以有多种方法

本例属于不相关子查询,就是查询条件不依赖于父查询。
下面一例就是相关子查询。

2.带有比较运算符的子查询

--找出每个学生超过他自己选修课程的课程号
select sno, cno
from sc x
where grade >= (	/*某个学生的平均成绩*/
	select avg(grade)
	from sc y
	where y.sno = x.sno);

这种子查询中与父查询有相关的,就叫相关子查询

3. 带有any或all谓词的子查询

/*查询非计算机系中比计算机系所有学生年龄都小的学生的姓名和年龄*/
select sname, sage
from student
where sage < all (
	select age
	from student
	where sdept='cs') and sdept <> 'cs';

4. 带有exists谓词的子查询

带有exists的子查询不返回数据,只返回逻辑真假值

/*查询所有选修了1号课程的学生*/
select sname
from student
where exisits(	/*判断这个学生是否选修了1号课程*/
	select *		/*这里select无意义,一般都写*号  */
	from sc
	where sno = student.sno and cno='1');

下面这个是经典,查询选修了全部课程的学生
这个思路就是,查询 不存在有一门课他没选
not exisits就是查询为空返回true

select sname
from student
where not exisits (	/*不存在,有门课没选的情况*/
	select *
	from course
	where not exisit (	/*不存在,*/
		select *
		from sc
		where sno=student.sno
			and cno=course.sno));

我猜测其内部其中一种情况就是,选取了一个学生,现在我们手上拿着这个学生的名字干这样的事。
遍历所有课程的表,拿出一个课程的名字,去看看sc表中有没有这两匹配的情况。查询出来肯定是有的,对于这一个学生和这一门课,not exists返回false然后继续看这一个学生和下一门课,这样下去,如果每一个都找到了,经过not exists就都是false,所以就是空的,再经过最外面的not exisits,因为是空的所以返回true,这个学生就被确保了选了所有课。再接着看下一轮。那如果一个学生和一门课在sc中没有被找到,not exist就会返回true,意识是这个学生确实有一门课没选,所以最外层不存在没有课选的情况就不对了,not exist会因为下一层的true而返回false,这个学生就没被选了。
这不是简单的双重否定表肯定,这个是不能换层单层用exist的,这有点想flag的思想,要保持一个false的状态,最后才能返回true,这样才确保遍历了每一门课。

四、集合查询

并操作union,交操作intersect,差操作except

/*查询选修了了课程1或课程2的学生*/
select sno
from sc
where cno='1'
union
select sno
from sc
where cno='2';

注意:

  1. 进行集合操作的查询结果,列数要相同,数据类型也要相同
  2. union会自动去掉重复元组,要全部显示就用union all

五、基于派生表的查询

其实就是子查询放在from里面,这样查询的表就是新生成的表,又叫做临时派生表

/*上例中,找出每个学生超过自己选修课程的平均成绩的课程号*/
select sno, cno
from sc, (
	select sno, avg(grade)
	from sc
	group by sno)
	as Avg_sc(avg_sno, avg_grade)
where sc.sno = Avg_sc.avg_sno and sc.grade >= Avg_sc.avg_grade;

总结

这就是复习巩固数据查询时候把课本内容和自己的理解做了各汇总,数据查询是很基础和关键的,接下来会做一个实验实战,看看有没有需要补充的点。


参考资料:数据库系统概论(第5版) 王珊 萨师煊 编著
上一篇:2021-11-15 基于音乐商店NetMusicShop的复杂查询(二)


下一篇:SQL数据更新