查询
计算列
1 | select * from emp |
distinct
过滤掉重复的值
1 | select deptno from emp |
between
1 | select * from emp where sal >= 1500 and sal <= 3000 |
in
1 | select * from emp where sal in (1500, 3000, 5000) |
top
最前面的若干记录
1 | select * from emp |
工资1500到3000的员工工资前4个人信息输出
1 | select top 5 * from emp where sal between 1500 and 3000 |
null
没有值,空值
任何类型都可以为null
1 | select * from emp where comm <> null --error |
输出每个员工的姓名,年薪(包含了奖金)comm是一年的奖金
1 | select ename, sal*12 + comm from emp --error |
1 | isnull(comm, 0) --如果comm 是空值,返回0, 否则返回comm的值 |
order by
以某个字段排序
1 | select * from emp order by sal --默认按升序排序 |
模糊查询
select 字段的集合 from 表名 where 字段的名字 like 匹配的条件
匹配的条件通常含有通配符
通配符:
% :任意0个或多个字符
1 | select * from emp where ename like '%A%' --只要含有字母A就输出 |
_ :任意单个字符
1 | select * from emp where ename like '_A%' --只要第二个字母是A就输出 |
[a-f] : a到f的任意单个字符
1 | select * from emp where ename like '_[A-F]%' |
[a,f] : a或f的任意单个字符
[~a-c] 不是(a-f)
1 | select * from emp where ename like '%\%%' escape '\' --把名字包含%的输出 |
聚合函数
多行记录返回一个值, 通常用于统计分组的信息
函数的分类
单行函数: 每一行返回一个值
多行函数: 多行返回一个值, 聚合函数是多行函数
例子:
1 | select lower(ename) from emp --lower()是单行函数 |
聚合函数的分类:
max()
min()
avg()
count(): 求个数
count(*) : 返回表中所有记录的个数
count(字段名) : 返回字段值非空的的记录的个数,重复的记录也会被当做有效的记录
count(distinct 字段名)
1 | select count(*) from emp --返回emp表中所有记录的个数 |
注意的问题:
1 | select max(sal),min(sal),count(*) from emp --correct |
group by
格式:
group by
字段的集合
功能:
把表中的记录按照字段分为不同的组
分组后只能出现分组后的整体信息,不能出现组内详细信息
1 | select deptno, avg(sal) as "部门平均工资" from emp group by deptno; -- |
group by a, b
先按a分组,再按b分组,最终统计的是最小分组的信息
1 | select deptno, job, avg(sal) as '平均' |
使用了group by 之后, select 中只能出现分组后的整体信息,不能出现组内的详细信息
having
对分组之后的信息进行过滤
1 | --输出部门平均工资大于2000的 部门编号 部门平均工资 |
判断下列sql语句是否正确
1 | select deptno, avg(sal) as "平均工资", count(*) as "部门人数" |
having 和 where 的异同
where对原始数据进行过滤
having对分组之后的数据进行过滤
所有select 参数的位置顺序不允许变化,否则编译出错
1 | --把姓名不包含A的所有员工按部门编号分组,统计输出部门平均工资大于2000的部门的 部门编号 部门的平均工资 |
- having 子句是用来对分组以后的数据进行过滤,因此使用having时通常先使用group by
- 如果没使用 group by 但使用了having,意味着having把所有的记录当作一组来进行过滤
1
2
3select count(*)
from emp
having avg(sal) > 1000 - having 子句出现的字段必须是分组之后的组的整体信息,不允许出现组内详细信息
- having 子句不能出现别名
连接查询
定义
将两个表或两个以上的表按一定条件连接起来,从中检索出满足条件的数据
内连接
1 | select "E".ename "员工姓名", "D".dname "部门名称" |
分类
select … from A, B
row = rowA * rowB
col = colA + colB
把A表的每一条记录和B表的每一条记录组合在一起,形成的是笛卡尔积
1 | select * from emp, dept |
select … from A, B where
1 | select * from emp, dept where empno = 7369 --5行 |
select … from A join B on …
1 | select "E".ename "员工姓名", "D".dname "部门名称" |
select … from A, B where … 与 select … from A join B on … 的区别
1 | select * from emp, dept |
1 | select * |
把工资大于2000的 员工的姓名 和 部门名称 和 工资等级 输出
sql99标准
1 | select "E".ename, "D".dname, "S".grade |
sql92标准
1 | select E.ename, D.dname, S.grade |
select from where join on group by order top having 混合使用
1 | --输出工资最高的前三名每个员工的姓名,工资,工资等级,部门名称 |
1 | --输出部门名称不包含A的所有员工中工资最高的前三名每个员工的姓名,工资,工资等级,部门名称 |
习题
- 求出每个员工的姓名 部门编号 薪水 薪水等级
1
2
3
4select "E".ename, "E".deptno, "S".grade
from emp "E"
join salgrade "S"
on "E".sal between "S".losal and "S".hisal - 查找每个部门的编号 该部门所有员工的平均工资 平均工资的等级
1
2
3
4select "T".deptno, "T".avg_sal, "S".grade
from (select deptno, avg(sal) as "avg_sal" from emp group by deptno) "T"
join salgrade "S"
on "T".avg_sal between "S".losal and "S".hisal - 求出emp表中所有领导的姓名求出所有非领导的姓名
1
2
3select *
from emp
where empno in (select mgr from emp)1
2
3select *
from emp
where empno not in (select mgr from emp) --error mgr 中含有null - 求出平均薪水最高的部门编号和部门的平均工资
1
2
3
4select top 1 deptno "部门的编号", avg(sal) "部门的平均工资"
from emp
group by deptno
order by avg(sal) desc - 把工资大于所有员工中工资最低的前3个人的姓名 工资 部门编号 工资等级输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20--第一种写法
select top 3 "E".ename, "E".sal, "E".deptno, "D".dname, "S".grade
from emp "E"
join dept "D"
on D.deptno = E.deptno
join salgrade "S"
on "E".sal between "S".losal and "S".hisal
where sal > (select min(sal) from emp)
order by sal
--第二种写法
select top 3 "T".ename, "T".sal, "T".deptno, "D".dname, "S".grade
from (
select * from emp "E" where sal > (select min(sal) from emp)
) "T"
join dept "D"
on "T".deptno = "D".deptno
join salgrade "S"
on "T".sal between "S".losal and "S".hisal
order by "T".sal
总结:
把工资大于1500的所有员工按部门分组, 把部门平均工资大于2000的最高前两个的部门编号,平均薪资,部门名称,平均工资对应的薪资等级输出
1 | --把工资大于1500的所有员工按部门分组, 把部门平均工资大于2000的最高前两个的部门编号,平均薪资,部门名称,平均工资对应的薪资等级输出 |
外连接
定义: 不但返回满足连接条件的所有记录,而且会返回部分不满足条件的记录
左外连接:不但返回满足条件的所有记录,而且还会返回部分左表不满足条件的记录
右外连接:不但返回满足条件的所有记录,而且会返回右表不满足条件的记录
1
2
3
4
5
6
7select * from emp "E"
left join dept "D"
on "E".deptno = "D".deptno --14行
select * from dept "D"
left join emp "E"
on "E".deptno = "D".deptno --16行
完全连接
1 | select * from dept "D" |
交叉连接
产生笛卡尔积
1 | select * from emp cross join dept |
自连接
一张表自己和自己连接起来查询数据
例子:
不准用聚合函数, 求薪水最高的员工的信息
1 | select * from emp where sal = (select max(sal) from emp) --使用聚合函数 |
联合
表和表之间的数据以纵向的方式联合在一起
注意:我们之前讲的所有连接都是以横向的方式连接在一起
若干个select子句要联合成功的话必须要满足两个条件:
- 这若干个select子句输出的列数必须是相等的
- 这若干个select子句输出的数据类型至少是兼容的
1 | --输出每个员工的姓名,工资,上司的姓名 |
嵌套查询
分页查询
***
*week10_1
1 | select getdate() |
week10_2
stuff
在字符串1中在指定的开始位置删除指定长度的字符,并在指定的开始位置处插入字符串2。返回新字符串
1 | select stuff('abcdef', 2, 3, '1234') |
1 | select convert(varchar, getdate(), 126) |
week11
1 | select count(studentid) from student group by gradeid |
week11_2
week12_1
1 | --考过试的学生姓名 |
week_12_2
1 |
|