MySQL基础——DQL语言(基础查询)
该部分内容是Mysql的基础核心部分,对于工作中大部分时间都是通过数据库来查询需要的数据然后再进行数据分析。
所以好好学咯!!!!!!
一、基础查询
Desc 表名; #查询表的结构
语法:
Select 查询列表
From 表名
特点:
1. 查询列表可以是:表中的字段、常量值、表达式、函数
2. 查询的结果是一个虚拟的表格
1. 查询表中的单个字段
Select last_name
from employees;
2.查询表中的多个字段
Select last_name,salary,email
from employees;
3.查询表中的所有字段
Select *
from employees;
4.查询常量值
Select 100;
5.查询表达式
Select 100%98;
6.查询函数
Select version();
7.起别名
作用:1.便于理解
2.如果要查询的字段有重名的情况,使用别名可以区分开来
方式一:
Select 100%98 as 结果;
Select last_name as 姓,first_name as 名
from employees;
方式二:
Select last_name 姓,first_name 名
from employees;
8.去重
案例:查询员工表中涉及到的所有的部门编号
Select distinct department_id
from employees;
9.+号的作用
Mysql中的+号仅仅只有一个功能:运算符
Select 100+90; 两个操作数都是数值型,则做加法运算
Select ‘123’+90; 只要其中一方为字符型,试图将字符型数值转换为数值型。
如果转换成功,则继续做加法运算
如果转换失败,则将字符型数值转换为0
Select null+10; 只要其中一方为null,则结果肯定为null.
案例:查询员工名和姓连接成一个字段,并显示为姓名
Select concat(last_name,first_name) as 姓名
from employees;
二、条件查询
语法:
select 查询列表 from 表名 where 筛选条件;
1、 按条件表达式筛选
a) 条件运算符:> < = != <> >= <=
案例一:查询工资>12000的员工信息
Select *
from employees
where salary>12000;
案例二:查询部门编号不等于90号的员工名和部门编号
Select last_name,department_id
from employees
where department_id <>90;
2、 按逻辑表达式筛选
a) 逻辑运算符:&& || !
And or not
案例一:查询工资在10000到20000之间的员工名、资金以及奖金
Select last_name,salary,commission_pct
from employees
where salary>=10000 and salary<=20000;
3、 模糊查询
a) Like
b) Between and
c) In
d) Is null
1). Like
特点:
1. 一般和通配符配合使用
a) % 代表任意多字符
b) _ 代表一个字符
案例一:查询员工名中包含字a的员工信息、
Select *
from employees
where last_name like ‘%a%’;
2).between and
1) 使用between and可以提高语句的简洁度
2) 包含临界值
3) 两个临界值不要调换顺序
案例一:查询员工编号在100到120之间的员工信息
Select *
from employees
where employee_id >=100 and employee_id<=120;
使用between and
Select *
from employees
where employees_id between 100 and 120;
3). in
含义:
判断某字段的值是否属于in列表中的某一项
特点:
1.使用in提高语句简洁度
2.in列表的值类型必须一致或兼容
3.在in后面的内容不支持通配符。
案例一:查询员工的工种编号是IT_PROG、AD_VP、AD_PRES中的一个员工名和工种编号
Select Last_name,Job_id
From Employees
Where Job_id = ‘IT_PROG’ or
job_id = ‘AD_VP’ or job_id = ‘AD_PRES;
使用in来实现
Select Last_name,Job_id
From Employees
Where Job_id in( ‘IT_PROG’,‘AD_VP’,‘AD_PRES);
4). Is null
注意:不能使用 = != <> 用于判断null值
案例一:查询没有奖金的员工名和奖金率
Select Last_name,Commission_pct
From Employees
Where Commission_pct is null;
案例二:查询有奖金的员工名和奖金率
Select Last_name,Commission_pct
From Employees
Where Commission_pct is not null;
5).安全等于 <=>
案例一:查询没有奖金的员工名和奖金率
Select Last_name,Commission_pct
From Employees
Where Commission_pct < => null;
案例二:查询工资为12000的员工信息
Select last_name,salary
from employees
where salary < = > 12000;
6).is null vs < = >
Is null :仅仅可以判断null值,可读性较高,建议使用
<=> :既可以判断null值,又可以判断普通的数值,可读性较低
三、排序查询
格式:
引入:select * from employees;
语法:
select 查询语句
From 表
Where 拆选条件
Order by 排序列【asc|desc_升序|降序】
特点:
1. Asc代表的是升序,desc代表的是降序,如果不写默认的是升序
2. order by 子句中可以支持单个字段、多个字段、表达式、函数、别名
3. order by 子句一般是放在查询语句的最后面,limit子句除外
案例一:查询员工信息,要求工资从高到低排序
Select *
from employees
order by salary desc;
案例二:查询部门编号>=90的员工信息,按照入职时间的先后进行排序
Select *
from employees
where employee_id >= 90
order by hiredate asc;
案例三:按年薪的高低显示员工的信息和年薪【按表达式排序】
Select *,salary*12*(1+ifnull(commission_pct,0)) 年薪
From employees
Order by salary*12*(1+ifnull(commission_pct,0)) desc;
案例四:按年薪的高低显示员工的信息和年薪【按别名排序】
Select *,salary*12*(1+ifnull(commission_pct,0)) 年薪
From employees
Order by 年薪desc;
案例五:按姓名的长度显示员工的姓名和工资【按函数排序】
Select length(last_name) 字节长度,last_name,salary
From employees
Order by length(last_name) Desc;
案例六:查询员工信息,要求先按工资排序,再按员工编号排序【按多个字段排序】
Select *
From employees
Order by salary asc,employee_id desc;
四、常见函数
概念:
将一组逻辑语句封装在方法体中,对外暴露方法名
好处:
1.隐藏了实现细节
2.提高代码的重用性
调用:
select 函数名(实参列表)【from 表】;
特点:
1.叫什么(函数名)
2.干什么(函数功能)
分类:
1.单行函数
如:concat、length、ifnull 等
2.分组函数‘
功能:
做统计使用,又称为统计函数、聚合函数、组函数
1、 字符函数
1)、Length:获取参数值的字节个数
Select length(‘john’);
Select length(‘张三丰hahaha’); #汉字包含3个字节
Show variables like ‘%char%’ #客户端字符集
2)、concat 拼接字符串
Select concat(last_name,’_’,first_name) 姓名
from employees;
3)、upper lower
Select upper(‘john’);
Select lower(‘joHn’);
案例:将姓变大写,名变小写,然后拼接
Select concat(upper(last_name),lower(first_name)) 姓名
from employees;
4)、substr 、subbstring
#截取从指定索引处后面所有字符
Select substr(‘李莫愁爱上了陆展元’,7) out_put; #sql语句中索引从 1 开始
#截取从指定索引处指定字符长度的字符
Select substr(‘李莫愁爱上了陆展元’,1,3) out_put;
案例:姓名中首字符大写,其他字符小写然后用_拼接,显示出来
Select concat(upper(substr(last_name,1,1))),’_’,lower(substr(last_name,2)) out_put
From employees;
5)、instr 返回子串第一次出现的索引,如果找不到返回0
Select instr(‘杨不悔爱上了殷六侠’,’殷六侠’) as output
From employees;
6)、 trim 去掉字符串的左右空格或所给出的字符
Select length(trim(‘ 张翠山 ’))
as out_put;
Select trim(‘a’ from ‘aaaaaaaaaaaaa张aaaa翠山aaaaaaaaaaa’)
as out_put;
7)、 lpad 用指定的字符实现左填充指定长度
Select lpad(‘殷素素’,10,’*’)
as out_put;
8)、rpad 用指定的字符实现右填充指定长度
Select rpad(‘殷素素’,2,’ab’)
as out_put;
9)、 replace 替换
Select replace(‘张无忌爱上了周芷若’,’周芷若’,’赵敏’)
as out_put;
2、 数学函数
1)、 round 四舍五入
select round(-1.55);
select round(1.567,2); #保留两位小数
2)、 ceil 向上取整,返回>=该参数的最小整数
select ceil(-1.02);
3)、 floor 向下取整,返回>=该参数的最大整数
select floor(-9.99);
4)、 truncate 截断
select truncate(1.65,1); #小数点后保留一位
5)、 mod 取余
格式:
mod(a,b) : a-a/b*b
select mod(10,3); #10%3 = 1
3、日期函数
1)、now 返回当前系统日期+时间
Select now();
2)、curdate 返回当前系统日期,不包含时间
Select curdate();
3)、curtime 返回 当前时间,不包含日期
Select curtime();
4)、可以获取指定的部分,年、月、日、小时、分组、秒
Select year(now()) 年;
Select month(now()) 月;
Select monthname(now()) 月;
5)、str_to_date:将日期格式的字符转换为指定格式的日期
日期格式符:
%Y 四位的年份
%y 2位的年份
%m 月份(01,02,…11,12)
%c 月份(1,2,…11,12)
%d 日(01,02…)
%H 小时(24小时制)
%h 小时(12小时制)
%i 分钟(00,01… 59)
%s 秒(00,01…59)
Str_to_date(‘9-13-1999’,%m-%d-%Y) #1999-09-13
6)、date_format:将日期转换为字符
Date_format(‘2018/6/6’,’%Y年%m月%d日’) #2018年06月06日
4、其他函数
Select version(); #查看当前版本号
Select database(); #查看当前数据库
Select user(); #查看当前用户
5、流程控制函数
1)、if函数:if else的效果
Select if(10>5,’大’,’小’);
#当判断条件为真。执行前者,为假执行后者
2)、case 函数的使用
a. case函数使用一:switch case的效果
在Java中
Switch(变量或表达式)
{case 常量1:语句1 ;break;
…
Default:语句n;break;
}
在mysql中:
Case 要判断的字段或表达式
When 常量1 then 要显示的值1或语句1;
When 常量2 then 要显示的值2或语句2;
…
Else 要显示的值n或语句n;
End
案例:查询员工的工资,要求:
部门号=30,显示的工资为1.1倍
部门号=40,显示的工资为1.2倍
部门号=50,显示的工资为1.3倍
其他部门,显示的工资为原工资
Select salary 原始工资,department_id,
Case department_id
When 30 then salary*1.1
When 40 then salary*1.2
When 50 then salary*1.3
Else salary
End as 新工资
From employees;
b. case函数使用二:类似于多重if
Java中:
If(条件1)
{
语句1;
}
Else if(条件2)
{
语句2;
}
Else
{
语句n;
}
Mysql中:
Case
When 条件1 then 要显示的值1或 语句1
When 条件2 then 要显示的值2或 语句2
…
Else 要显示的值n或语句n
End
案例:查询员工的工资的情况
如果工资>20000,显示A级别
如果工资>15000,显示B级别
如果工资>10000,显示C级别
否则,显示D级别
Select salary,
Case
When salary>20000 then ’A’
When salary>15000 then ‘B’
When salary>10000 then ‘C’
Else ‘D’
End as 工资级别
From employees;
五、分组函数
功能:
用于统计使用,又称为聚合函数或统计函数或组函数
分类:
Sum求和、avg平均值、max最大值、min最小值、count计算个数
1、 简单的使用
Select sum(salary) from employees;
Select avg(salary) from employees;
Select max(salary) from employees;
Select min(salary) from employees;
Select count(salary) from employees;
Select sum(salary) 和,avg(salary) 平均,
max(salary) 最高,min(salary) 最低,
count(salary) 个数
From employees;
Select sum(salary) 和,round(avg(salary),2) 平均,
max(salary) 最高,min(salary) 最低,
count(salary) 个数
From employees;
2、 参数支持哪些类型
1、 sum avg 一般用于处理数值型
2、 max min count可以处理任何类型
3、是否忽略null
五个分组函数均忽略null值
4、和distinct搭配
Select sum(distinct salary),sum(salary)
from employees;
Select count(distinct salary),count(salary)
from employees;
五个分组函数均可以和distinct(去重函数)搭配使用
5、count函数的详细介绍
Select count(salary)
from employees;
Select count(*)
from employees;
Select count(1)
from employees; #相当于在表中添加一列 1 ,进行统计行数
效率:
以前:MYSAM存储引擎下 count() 的效率高
现在:INNODB存储引擎下 count()和count(1)的效率差不多,比count(字段)要高一些
6、和分组函数一同查询的字段有限制
Select avg(salary),employee_id
from employees; #此时的employee_id仅显示一个值
和分组函数一同查询的字段要求是group by后的字段
六、分组查询
语法:
Select 分组函数,列(要求出现在group by的后面)
From 表
Where 筛选条件
Group by 分组的列表
Order by 子句序排列
注意:
查询列表必须特殊,要求是分组函数和group by 后出现的字段
特点:
1. 分组查询中的筛选条件分为两类
分组前筛选:
数据源—原始表、位置—group by子句的前面、关键字—where
分组后筛选:
数据源—分组后的结果集、位置—group by子句的后面、关键字—having
1)分组函数做条件肯定是放在having子句中
2)能用分组前筛选的,就优先考虑使用分组前筛选
2. group by 子句支持单个字段分组,多个字段分组(多个字段之间用逗号隔开没有顺序要求),表达式或函数(用的较少)
3. 也可以添加排序(排序放在整个分组查询的最后)
1、简单的分组查询
案例一:查询每个工种的最高工资
Select avg(salary),job_id
From employees
Group by job_id;
案例二:查询每个位置上的部门个数
Select count(*),location_id
From departments
Group by location_id;
2、添加筛选条件
案例一:查询邮箱中包含a字符的,每个部门的平均工资
Select avg(salary),department_id
From employees
Where email like ‘%a%’
Group by department_id;
案例二:查询有奖金的每个领导手下员工的最高工资
Select max(salary),manager_id
From emploees
Where commission_pct is not null
Group by manager_id;
3、添加复杂的筛选条件
案例一:查询哪个部门的员工个数>2
#1. 查询每个部门的员工个数
Select count(*),department_id
From employees
Group by department_id;
#2. 根据1 的结果进行筛选,查询哪个部门的员工个数>2
Select count(*),department_id
From employees
Group by department_id
Having count(*)>2;
案例二:查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
#1. 查询每个工种有奖金的员工的最高工资
Select max(salary),job_id
From employees
Group by job_id;
#2. 根据1 结果继续筛选,最高工资>12000
Select max(salary),job_id
From employees
Where commission_pct is not null
Group by job_id
Having max(salary)>12000;
案例三:查询领导编号>102的每个领导手下的最低工资>5000的领导编号时哪个,以及其最低工资
#1. 查询每个领导手下的员工固定最低工资
Select min(salary),manager_id
From employees
Group up manager_id;
#2. 添加筛选条件:领导编号>102
Select min(salary),manager_id
From employees
Where manager_id>102
Group up manager_id;
#3. 最低工资>5000
Select min(salary),manager_id
From employees
Where manager_id>102
Group up manager_id
Having min(salary)>5000;
4、按表达式分组
案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些
#1. 查询每个长度的员工个数
Select count(*),length(last_name) len_name
From employees
Group by length(last_name);
#2. 添加筛选条件
Select count(*),length(last_name) len_name
From employees
Group by length(last_name)
Having count(*)>5;
5、按多个字段分组
案例:查询每个部门每个工种的员工的平均工资
Select avg(salary),department_id,job_id
From employees
Group by department_id,job_id;
6、添加排序
案例:查询每个部门每个工种的员工的平均工资,并且按平均工资的高低显示
Select avg(salary),department_id,job_id
From employees
Group by department_id,job_id
Order by avg(salary) desc;
七、连接查询
含义:
又称多表查询,当查询的字段来自于多个表时,就会用到连接查询
笛卡尔乘积现象:
表1 有m行,表2 有n行,结果 = m*n 行
发生原因:没有有效的连接条件
如何避免:添加有效的连接条件
分类:
按年代分类:sql92标准(仅支持内连接)、sql99标准(支持内连接+外连接(左外和右外)+交叉连接)
按功能分类:内连接:等值连接、非等值连接、自连接
外连接:左外连接、右外连接、全外连接
交叉连接
(一)、 sql92标准
1、 等值连接
a. 多表等值连接的结果为多表的交集部分
b. N表连接,至少需要n-1个连接条件
c. 多表的顺序没有要求
d. 一般需要为表起别名
e. 可以搭配前面介绍的所有子句使用,比如:排序、分组、筛选
案例一:查询女神名和对应的男神名
Select name,boyname
From boys,beauty
Where beauty.boyfriend_id = boys.id;
案例二:查询员工名和对应的部门名
Select last_name,department_id
From employees,departments
Where employees.department_id = departments.department_id;
1).为表起别名
提高语句的简洁度,区分多个重名的字段
注意:如果为表起了别名,则查询的字段就不能使用原来的表名去限定
案例:查询员工名、工种名、工种号
Select e.last_name,e.job_id,j.job_title
From employees e,jobs j
Where e.job_id = j.job_id;
2)、两个表的顺序是否可以调换
案例:查询员工名、工种号、工种名
Select e.last_name,e.job_id,j.job_title
From jobs j,employees e
Where e.job_id = j.job_id;
3)、可以加筛选??
案例:查询有奖金的员工名、部门名
Select last_name,department_name
From employees e,department d
Where e.department_id = d.department_id
And e.commission_pct is not null;
案例二:查询城市名中第二个字符为o的部门名和城市名
Select department_name,city
From departments d,location l
Where d.location_id=l.location_id
And city like '_o%'
4)、可以加分组???
案例一:查询每个城市的部门个数
Select count(*) 个数,city
From department d,locations l
Where d.location_id=l.location_id
Group by city;
案例二:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资
Select min(salary),department_name,d.manager_id
From employees e,departments d
Where d.department_id=e.department_id
And commission_pct is not null
Group by department_name,d.manager_id;
5)、可以加排序??
案例:查询每个工种的工种名和员工的个数,并且按员工个数降序
Select job_title,count(*)
From employees e,jobs j
Where e.job_id=j.job_id
Group by job_title
Order by count(*) desc;
6)、可以实现三表连接???
案例:查询员工名、部门名和所在的城市
Select last_name,department_name,city
From employees e,departments d,location l
Where e.department_id=d.department_id
And d.location_id=l.location_id;
2、非等值连接
案例一:查询员工的工资和工资级别
Select salary,grade_level
From employees e,job_grades g
Where salary between g.lowest_sal and g.highest_sal;
3、自连接
案例:查询员工名和上级的名称
Select e.employee_id,e.last_name,m.employee_id,m.last_name
From employees e,employees m
Where e.manager_id=m.employee_id;
(二)、sql99语法
语法:
Select 查询列表
From 表1 别名 【连接类型】
Join 表2 别名
On 连接条件
Where 筛选条件
Group by 分组
Having 筛选条件
Order by 排序列表
连接类型分类:
内连接(★):inner
外连接
左外★:left【outer】
右外★:right【outer】
全外:full 【outer】
交叉连接:cross
1、内连接
语法:
Select 查询列表
From 表1 别名
Inner join 表2 别名
On 连接条件;
分类:
等值
非等值
自连接
特点:
a. 添加排序、分组、筛选
b. Inner可以省略
c. 筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读
d. Inner join 连接和sql92中的等值连接效果是一样的,都是查询多表的交集
1)等值连接
案例一:查询员工名、部门名
Select last_name,department_name
From employees e
Inner join department d
On e.department_id = d.department_id;
案例二:查询名字中包含e的员工名和工种名(添加筛选)
Select last_name,job_title
From employees e
Inner join jobs j
On e.job_id = j.job_id
Where e.last_name like ‘%e%’;
案例三:查询部门个数>3 的城市名和部门个数(添加分组+筛选)
Select city,count(*) 部门个数
From departments d
Inner join locations l
On d.location_id = l.location_id
Group by city
Having count(*)>3;
案例四:查询哪个部门的部门员工个数>3 的部门名和员工名,并按个数降序(添加排序)
Select department_name,count(*)
From employees e
Inner join departments d
On e.department_id = d.department_id
Group by department_name
Having count(*)>3
Order by count(*) desc;
案例五:查询员工名、部门名、工种名,并按部门名降序排列
Select last_name,department_name,job_title
From employees e
Inner join departments d on e.department_id = d.department_id
Inner join jobs j on e.job_id = j.job_id
Order by department_name desc;
2)非等值连接
案例一:查询员工的工资级别
Select salary,grade_level
From employees e
Join job_grades g
On e.salary between g.lowest_sal and g.highest_sal;
案例二:查询每个工资级别的个数>20的个数,并且按工资级别降序排列
Select count(*),grade_level
From employees e
Join job_grades g
On e.salary between g.lowest_sal and g.highest_sal;
Group by grade_level
Having count(*)>20
Order by grade_level desc;
3)自连接
案例:查询姓名中包含字符‘k’的员工的名字、上级的名字
Select e.last_name,m.last_name
From employees e
Join employees m
On e.manager_id = m.employee_id
Where e.last_name like '%k%';
2、外连接
应用场景:
用于查询一个表中有,另一个表中没有的记录
特点:
1、 外连接的查询结果位主表中的所有记录
a) 如果从表中有和它匹配的,则显示匹配的值
b) 如果从表中没有和它匹配的,则显示null
c) 外连接查询结果 = 内连接结果+主表中有而从表没有的记录
2、 左外连接,left join 左边的是主表
右外连接,right join 右边的是主表
3、左外和右外交换两个表的顺序,可以实现同样的结果
4、全外连接=内连接结果+表1中有但表2中没有的+表2中有但表1没有的
引入:查询男朋友,不在男神表的女神名
Select * from beauty;
Select * from boys;
1)、左外连接
Select b.name,bo.*
From beauty b
Left outer join boys bo
On b.boyfriend_id = bo.id
Where bo.id is null;
2)、右外连接
Select b.name,bo.*
From boys bo
right outer join beauty b
On b.boyfriend_id = bo.id
Where bo.id is null;
案例:查询哪个部门没有员工
#左外连接
Select d.*,e.employee_id
From departments d
Left outer join employees e
On d.department_id = e.department_id
Where e.employee_id is null;
#右外连接
Select d.*,e.employee_id
From employees e
right outer join departments d
On d.department_id = e.department_id
Where e.employee_id is null;
3)、全外连接(在sql92和sql99中均不支持,即MySQL不支持)
全外连接就是,将两表中的交集、表2有表1没有的、表1有表2没有的,放在一起。没有的位置打印null值
3、交叉连接
原理:使用sql99语法实现笛卡尔乘积
案例:
Select b.*,bo.*
From beauty b
Cross join boys bo;
八、子查询
含义:
出现在其他语句中的select语句,称为子查询或内查询
外部的查询语句,称为主查询或外查询
分类:
按子查询出现的位置:
Select后面:仅仅支持标量子查询
From后面:支持表子查询
Where或having后面:标量子查询(★)、列子查询(★)、行子查询
Exists后面(相关子查询):表子查询
按结果集的行列数不同:
标量子查询(结果集只有一行一列)
列子查询(结果集只有一列多行)
行子查询(结果集有一行多列)
表子查询(结果集一般位多行多列)
Eg:
Select first_name from employees where
Department_id in(
Select department_id from departments
Where location_id = 1700)
1、where或having 后面
1.标量子查询(单行子查询)
2.列子查询(多行子查询)
3.行子查询(多列多行)
特点:
1. 子查询放在小括号内
2. 子查询一般放在条件的右侧
3. 标量子查询,一般搭配着单行操作符使用: >< >= <= <>
列子查询,一般搭配着多行操作符使用
In 、any/some、all
4. 子查询的执行优先于主查询执行,
主查询的条件用到了子查询的结果
1)、 标量子查询
案例一:谁的工资比Abel高?
#1. 查询Abel的工资
Select salary
From employees
Where last_name = ‘Abel’
#2. 查询员工的信息,满足salary>1
Select *
From employees
Where salary>(
Select salary
From employees
Where last_name = ‘Abel’);
案例二:返回job_id与141号员工相同,salary比143号员工多的员工姓名,job_id和工资
#1. 查询141号员工的job_id
Select job_id
From employees
Where employee_id = 141
#2. 查询143号员工的salary
Select salary
From employees
Where employee_id = 143
#3. 查询员工的姓名,job_id和工资,要求job_id=1并且salary>2
Select last_name,job_id,salary
From employees
Where job_id = (
Select job_id
From employees
Where employee_id = 141
)
And salary>(
Select salary
From employees
Where employee_id = 143);
案例三:返回公司工资最少的员工的last_name,job_id和salary
Select last_name,job_id,salary
From employees
Where salary=(
Select min(salary)
From employees);
案例四:查询最低工资大于50号部门最低工资的部门id和其最低工资
#1. 查询50号部门的最低工资
Select min(salary)
From employees
Where department_id = 50
#2. 查询每个部门的最低工资
Select min(salary),department_id
From employees
Group up department_id
#3. 筛选2,满足min(salary)>1
Select min(salary),department_id
From employees
Group by department_id
Having min(salary)>(
Select min(salary)
From employees
Where department_id = 50);
注意:非法使用标量子查询案例
Select min(salary),department_id
From employees
Group by department_id
Having min(salary)>(
Select salary
From employees
Where department_id=50);
2)、列子查询(多行子查询)
In/not in:等于列表中的任意一个
Any|some:个子查询返回的某一个值比较
All:和子查询返回的所有值比较
案例一:返回location_id是1400或1700的部门中的所有员工姓名
Select last_name
From employees
Where department_id in(
Select distinct department_id
From departments
Where location_id in(1400,1700));
案例二:返回其他工种中比job_id为 IT_PROG部门任一工资低的员工的:工号、姓名、job_id以及salary
#1. 查询job_id为IT_PROG部门任一工资
Select distinct salary
From employees
Where job_id = ‘IT_PROG’
#2. 查询员工号、姓名、job_id以及salary,salary<1的任意一个
Select last_name,employee_id,job_id,salary
From employees
Where salary<any(
Select distinct salary
From employees
Where job_id = ‘IT_PROG’
) and job_id <> ‘IT_PROG’;
案例三:返回其他部门中比job_id为’IT_PROG’部门所有工资都低的员工的员工号、姓名、job_id、以及salary
Select last_name,employee_id,job_id,salary
From employees
Where salary<all(
Select distinct salary
From employees
Where job_id = 'IT_PROG')
and job_id<>'IT_PROG';
3)、行子查询(结果集一行多列或多行多列)
案例:查询员工编号最小并且工资最高的员工信息
Select *
From employees
Where (employees_id,salary)=(
Select min(employee_id),max(salary)
From employees);
#1. 查询最小的员工编号
Select min(employee_id)
From employees
#2. 查询最高工资
Select max(salary)
From employees
#3. 查询员工信息
Select *
From employees
Where employee_id = (
Select min(employee_id)
From employees
) and salary =(
Select max(salary)
From employees
);
2、select后面
案例一:查询每个部门的员工个数
Select d.*,(
Select count(*)
From employees e
Where e.department_id = d.department_id
) 个数
From department d;
案例二:查询员工号=102 的部门名
Select(
Select department_name
From departments d
Inner join employees e
On d.department_id=e.department_id
Where e.employee_id = 102
) 部门名;
3、from后面
案例:查询每个部门的平均工资的工资等级
#1.查询每个部门的平均工资
Select avg(salary),department_id
From employees
Group by department_id
#2.连接1的结果集和job_grade表,筛选条件平均工资between lowest_sal and highest_sal
Select ag_dep.*,g.grade_level
From(
Select avg(salary) ag,department_id
From employees
Group by department_id
) ag_dep
Inner join job_grades g
On ag_dep.ag between lowest_sal and highest_sal;
4、exists后面(相关子查询)
语法:
Exists(完整的查询语句)
结果:
1或0
Select exists(select employee_id from employees where salary= 300000);
案例一:查询有员工的部门名
Select department_name
From departments d
Where exists(
Select *
From employees e
Where d.department_id = e.department_id
);
案例二:查询没有女朋友的男神信息
Select bo.*
From boys
Where bo.id not in(
Select boyfriend_id
From beauty
);
#exists
Select bo.*
From boys bo
Where not exists(
Select boyfriend_id
From beauty b
Where bo.id=b.boyfriend_id
);
九、分页查询
应用场景:
当要显示的数据,一页显示不全,需要分页提交sql请求
语法:
Select 查询列表
From 表
【Join type】 join 表2
On 连接条件
Where 筛选条件
Group by 分组字段
Having 分组后的筛选
Order by 排序的字段
Limit 【offset】,size;
#offset要显示条目的起始索引(起始索引从0开始)
#size要显示的条目个数
特点:
1. limit语句放在查询语句的最后
2. 公式
要显示的页数page,每页的条目数size
Select 查询列表
From 表
Limit (page-1)*size,size
案例一:查询前五条员工信息
Select * from employees limit 0,5;
Select * from employees limit 5; #默认从0开始索引
案例二:查询第11条——第25条
Select * from employees limit 10,15;
案例三:有奖金的员工信息,并且工资较高的前10名显示出来
Select *
From employees
Where commission_pct is not null
Order by salary desc
Limit 10;
十、联合查询
Union联合 合并:
将多条查询语句的结果合并成一个结果
引入的案例:查询部门编号>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; #结果个上面一样
应用场景:
要查询的结果来自于多个表,且多个表没有直接的连接关系,
但查询的信息一致时
特点:
1. 要求多条查询语句的查询列数时一致的
2. 要求多条查询语句的查询的每一列的类型和顺序最好一致
3. Union关键字默认去重,如果使用union all 可以包含重复项
案例:查询中国用户中男性的信息以及外国用户中男性的用户信息
Select id,cname,csex
From t_ca
Where csex = ‘男’
Union
Select t_id,tname,tgender
From t_ua
Where tgender = ‘male’;