数据库学习记录02
DQL【数据查询语言】
1.基础查询
1.1语法
select * | {[DISTINCT] column | expression[alias], ...} from table;
特点
查询列表可以是表中的字段、常量值、表达式、函数。
查询的结果是一个虚拟的表格。
#1.查询表中的单个字段
select name from employees;
#2.查询表中的多个字段
select name, salary, gender from employee;
#3.查询表中的所有字段,能查字段尽量别用
select * from employees;
#4.查询常量值
select 100;
select 'join';
#5.查询表达式
select 100%98;
#6.查询函数
select version();
#7.起别名,如果要查询的字段有重名额情况,使用别名可以区分开来
#方式一:使用as
select 100%98 as 结果;
select name as 姓名, salary as 薪资 from employees;
#方式二:使用空格
select name 姓名, salary 薪资 from employees;
#8.DISTINCT 去重
select distinct department_id from employees;
1.2 +号的作用
#两个操作数都为数值型,则做加法运算
select 100+90;
#只要其中一方为字符型,则试图将字符型数值转换成数值型。如果转换成功,则继续做加法运算
select '123' + 90
#如果转换失败,则将字符型数值转换成0
select 'john'+90
#只要其中一方为null,则结果肯定为null
select null+10;
1.3 CONCAT、ISNULL、IFNULL
concat:合并两个字符串
select concat('a','b','c') as 结果;
#结果为:abc
ISNULL: 判断某字段或表达式是否为null,是返回1,否则返回0
select isnull('a') as 结果;
# 结果是: 0
IFNULL:如果第一个参数的表达式 expression 为 null,则返回第二个参数的备用值,可嵌套使用
select ifnull(commission , 0 ) as 奖金率, commission from employees;
2.条件查询
语法
select 查询列表 from 表名 where 筛选条件;
- 根据条件表达式筛选
用于筛选数据
操作符 | 说明 |
---|---|
= | 等于 |
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
<> | 不等于,等价于!= |
- 按逻辑表达式筛选
用于连接条件表达式
操作符 | 说明 |
---|---|
and | 与,逻辑并 |
or | 或,逻辑或 |
not | 非,逻辑否 |
范围查询
不确定条件进行范围查询,或者模糊查询
操作符 | 说明 |
---|---|
between | 在A和B之间,包含两边边界 |
in | 等于列表中的一个 |
like | 模糊查询,需要跟%一起用 |
is null | 空值,仅仅可以判断NULL值,可读性较高,建议使用 |
is not null | 非空值 |
<=> | 安全等于,既可以判断NULL值,又可以判断普通的数值,可读性较低 |
#按条件表达式筛选
/*
一般和通配符搭配使用
通配符:
% 任意多个字符,包含0个字符
_任意单个字符
*/
#案例1:查询员工名中包含字符a的员工信息
select * from employees where last_name like '%a%'; #abc
#案例2:查询员工名中第三个字符为e,第五个字符为a的员工名和工资
select last_name,salary from employees where last_name LIKE '__e_a%';
#案例3:查询员工名中第二个字符为_的员工名
select last_name from employees where last_name like '_$_%' escape '$'; #指定$为转移字符
#where last_name like '_\_%';
#2.between and
/* 使用between and 可以提高语句的简洁度,包含临界值,
两个临界值不要调换顺序
*/
#案例: 查询员工编号在100到120之间的员工信息
select * from employees where employee_id >=100 and employee_id <=120
select * from employees where employee_id between 100 and 120;
#3.in
/*含义:判断某字段的值是否属于in列表中的某一项*/
特点:使用in提高语句简洁度,in列表的值类型必须一致或兼容,in列表中不支持通配符
select last_name,job_id from employees where job_id = 'IT_PROT' or job_id = 'AD_VP' or job_id = 'AD_PRES';
select last_name, job_id from employees where job_id in ('IT_PROT','AD_VP','AD_PRES');
#4.is null
# =或<>不能用于判断null值 is null 或 is not null 可以判断null值
#案例1:查询没有奖金的员工名和奖金率
select last_name, commission_pct from employees where commission_pct is null;
#案例2: 查询有奖金的员工名和奖金率
select last_name, commission_pct from employees where commission_pct is not null;
#5.<=>
#案例1:查询没有奖金的员工名和奖金率
select last_name,commission_pct from employees where commission_pct <=> null;
#案例2:查询工资为12000的员工信息
select last_name,salary from employees where salary <=> 12000;
3.排序查询
语法
select 要查询的东西 from 表 where 条件 order by 排序的字段|表达式|函数|别名 [asc|desc];
- asc代表的是升序,为默认值,可以省略,desc代表的是降序
- order by 字句可以支持单个字段、别名、表达式、函数、多个字段
- order by字句在查询语句的最后面,除了limit字句
案例
#1.按单个字段排序
select * from employees order by salary desc;
#2.添加筛选条件再排序
#案例:查询部门编号>=90的员工信息,并按员工编号降序
select * from employees where departemnt_id >=90 order by employee_id desc;
#3.按表达式排序
#案例:查询员工信息 按年薪降序
select *, salary*12*(1+ifnull(commission_pct,0)) from employees
order by salary*12*(1+ifnull(commission_pct,0)) desc;
#4.按别名排序
#案例:查询员工信息,按年薪升序
select *, salary*12*(1+ifnull(commision_pct,0)) 年薪 from employees order by 年薪;
#5.按函数排序
#案例:查询员工名,并且按名字的长度降序
select length(last_name), last_name from employees order by length(last_name) desc;
#6.按多个字段排序
#案例:查询员工信息,要求先按照工资降序,再按employee_id升序
select * from employees order by salary desc, employee_id asc;
#7.查询员工的姓名和部门号和年薪,按年薪降序 按姓名升序
select last_name, departemnt_id, salary*12*(1+ifnull(commission_pct,0)) 年薪 from employees
order by 年薪 desc, last_name asc;
#8.选择工资不在8000到17000的员工的姓名和工资,按工资排序
select last_name, salary from employees where salary not bewteen 8000 and 17000 order by salary desc;
#9.查询邮箱中包含e的员工信息,并先按邮箱的字节数降序,再按部门号升序
select *, length(email) from employees where email like '%e%' order by length(email) desc, department_id asc;
4.内置函数
类似于java中的方法,将一组逻辑语句封装再方法体中,对外暴露方法名
优点:隐藏了实现细节,提高了代码的重用性
调用
select 函数名(实参列表) [from 表];
分类
- 单行函数
如concat、length、ifnull等
- 分组函数
功能:做统计使用,又称为统计函数、聚合函数、组函数
单行函数
字符函数
函数 | 说明 |
---|---|
length() | 获取字节个数(utf-8一个汉字代表3个字节,gbk为2个字节) |
concat() | 拼接 |
substring() | 截取字串 |
upper() | 转换成大写 |
lower() | 转换成小写 |
trim() | 去前后指定的空格或指定字符 |
ltrim() | 去左边空格 |
rtrim() | 去右边空格 |
replace() | 全部替换 |
lpad() | 左填充 |
rpad() | 右填充 |
instr() | 返回字串第一次出现的索引,找不到返回0 |
数学函数
函数 | 说明 |
---|---|
round() | 四舍五入 |
floor() | 向下取整 |
ceil() | 向上取整 |
mod() | 取余 |
truncate() | 截断 |
rand() | 产生0-1之间的一个随机数 |
日期函数
函数 | 说明 |
---|---|
now() | 当前系统日期+时间 |
curdate() | 当前系统日期 |
curtime() | 当前系统时间 |
str_to_date() | 将字符转换成日期 |
date_format() | 将日期转化成字符 |
year() | 获取年 |
month() | 获取月 |
monthname() | 获取月名称 |
day() | 天 |
hour() | 小时 |
minute() | 分钟 |
second() | 秒 |
datediff() | 返回两个时间差了多少天 |
datediff() | 两个时间相差的天数 |
其他函数
函数 | 说明 |
---|---|
version() | 版本 |
database() | 当前库 |
user() | 当前连接用户 |
md5('用户名') | 返回字符的密码形式 |
流程控制函数
都是处理分支情况
函数 | 说明 |
---|---|
if() | 处理等值判断 |
case语句 | 处理条件判断 |
分组函数
- sum和avg一般用于处理数值型,max、min、count可以处理任何数据类型
- 以上五个分组函数都忽略null值,都可以搭配distinct使用,用于统计去重后的结果
- count的参数都可以支持:字段、*、常量值(一般放1),建议使用count(*)
- 和分组函数一同查询多的字段要求是group by后的字段
函数 | 说明 |
---|---|
sum() | 求和 |
max() | 最大值 |
min() | 最小值 |
avg() | 平均值 |
count() | 计数 |
分组查询
语法
select 分组函数 groupby后的字段 from 表 [where 筛选条件]
group by 分组的字段
[having 筛选条件] [order by 排序的字段];
特点
- 和分组函数一同查询的字段最好是分组后的字段,或聚合函数
- 分组查询筛选分为两类
- 分组函数做条件放在having字句中
- 能用分组前筛选的,就优先考虑分组前筛选,处于性能考虑。
- 支持单个字段分组,也支持多个字段分组,字段之间用逗号隔开,没有顺序要求,也支持函数和表达式
- 可以添加排序,放在分组查询的最后
- group by 和 having 后可以支持别名,但不能用,因为Oracle等不支持。
#1.案例1:查询每个工种的员工平均工资
select avg(salary), job_id from employees group by job_id;
#2.案例2:查询邮箱中包含a字符的 每个部门的最高工资
select max(salary), department_id from employees where email like '%a%'
group by department_id;
#3.案例:查询哪个部门的员工个数>5
select count(*),department_id from employees group by department_id having count(*) > 5;
多表连接查询
含义及现象
含义
又称多表查询, 当查询的字段来自于多个表时,就会用到连接查询。
- 笛卡尔积乘积现象:表1 有m行,表2有n行,结果= m*n行。原因是因为没有有效的连接条件,需要添加有效的连接分类条件。
- 为表取别名:提高语句的简洁度,区分多个重名的字段,需要注意的是:如果表起了别名,则查询的字段就不能使用原来的表名去限定。
分类
内连接
关键字:inner join
1.等值连接 2.非等值连接 3.自连接
外连接
关键字:left join、right join
1.左外连接 2.右外连接 3.全外连接(MySQL不支持)
交叉连接
关键字:cross join
用来返回连接表的笛卡尔积
语法
inner join 内连接时,inner 可以省略,默认join就是指内连接
select 字段, ... from 表1
[inner | left outer | right outer | cross] join 表2 on 连接条件
[inner | left outer | right outer | cross] join 表3 on 连接条件
[where 筛选条件]
[group by 分组字段]
[having 分组后的筛选字段]
[order by 排序的字段后表达式]
子查询
含义:
出现在其他语句中的select语句,称为子查询或 内查询
子查询出现的位置
select 后面 仅仅支持标量子查询 from 后面 支持表子查询
where 或 having后面 标量子查询(单行) 列子查询(单列多行) 行子查询 表子查询 (多列)
exists 后面 (相关子查询)表子查询
特点
- 子查询放在小括号内
- 子查询一般放在条件的右侧
- 标量子查询,一般搭配着单行操作符使用
- >、<、>=、<=、=、<>
- in、any/some、all
- 列子查询,一般搭配着多行操作符使用
非相关子查询的执行优先于主查询执行,主查询的条件用到了子查询的结果
例如:
#in后面()里的就是子查询
select A.key from A where A.key in (select B.key from B);
分页查询
语法
select 查询列表 from 表 join 表2 on 连接条件 where 筛选条件
group by 分组条件 having 分组后的 筛选 order by 排序的字段
limit [offset,] size;
- offset表示要显示条目的起始索引(起始索引从0开始)
- size表示要显示的条目个数
特点
起始条目索引从0开始
limit字句放在查询语句的最后
公式: select * from 表 limit (page-1)*pageSize, pageSize
- pageSize: 每页显示条目数
- page:要显示的页数
例子:
#案例1:查询前五条员工信息
select * from employees limit 0, 5;
select * from employees limit 5;
#案例2:查询第11条-第25条
select * from employees limit 10,15;
#案例3:查询带有奖金的员工信息,并且显示工资较高的前10名
select * from employees where commission_pct is not null
order by salary desc limit 10;
联合查询
语法
查询语句1 union 查询语句 2 union ... 查询语句 n
特点
- 要求多条查询语句的查询列数是一致的
- 要求多条查询语句的查询的每一列的类型和顺序最好一致
- union关键字默认去重,如果使用union all 可以包含重复项
#案例1:查询部门编号>90 或邮箱包含a的员工信息
select * from employees where email like '%a%' or department_id > 90;
select* from employees where email like '%a%'
union
select * from employees where department_id > 90;
#案例2:查询中国用户男性的信息和外国用户中年男性的用户信息
select id, cname from t_ca where csex = '男'
union all
select t_id, tname from t_ua where tGender = 'male';
UNION和UNION ALL的区别
区别1:取结果的并集
- union: 对两个结果集进行并集操作,不包括重复行,相当于distinct,同时进行默认规则排序,
- union all: 对两个结果集进行并集操作,包括重复行,即所有的结果全部显示不管是不是重复。
区别2:获取结果后的操作
- union:会对获取的结果进行排序操作;
- union all: 不会对获取的结果进行排序;
区别3:
- 相同查询SQL条件下,union all的执行效率要比union高。