前两篇主要是查询查询查询,这是第一篇:
我半途而废的学习笔记之 MySQL (1)
其余内容我放在这里了 -->这里。
个人感觉查询这块知识点有些繁琐,反正我到后面就是在赶进度了,而且很多案例是一题多解的,用前面的知识点也完全OK,只是为了讲这个知识点强行安排,所以我取了很多小标题,方便翻查。
************************
引入:
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;
#升序
SELECT
*
FROM
employees
ORDER BY
salary ASC;
SELECT
*
FROM
employees
WHERE
department_id >= 90
ORDER BY
hiredate ASC;
SELECT
*,
salary * 12 *(
1+IFNULL ( commission_pct, 0 )) AS 年薪
FROM
employees
ORDER BY
salary * 12 *(
1+IFNULL ( commission_pct, 0 )) DESC;
SELECT
*,
salary * 12 *(
1+IFNULL ( commission_pct, 0 )) AS 年薪
FROM
employees
ORDER BY
年薪 DESC;
SELECT
LENGTH( last_name ) AS 字节长度,
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、单行函数(字符函数,数学函数,日期函数,其他函数,流程控制函数)
如concat、length、ifnull等
2、分组函数
功能:做统计使用,又称为统计函数、聚合函数、组函数
字符函数:
length:获取字节长度
concat:连接
substr:截取子串
instr:获取字串第一次出现的索引
trim:去掉前后空格
upper:变大写
lower:变小写
lpad:左填充
rpad:右填充
replace:替换
数学函数:
round:四舍五入
ceil:向上取整
floor:向下取整
truncate:截断
mod:去模
rand:获取随机数,返回0 - 1之间的小数
日期函数:
now:当前日期+时间
curdate:返回当前日期
curtime:返回当前时间
monthname:以英文姓氏返回月
year:年
month:月
day:日
hour:小时
minute:分钟
second:秒
datediff:两个日期之间的差的天数
str_to_date:将字符转换成日期
date_format:将日期转换成字符
其他函数:
version:当前服务器的版本
database:当前打开的数据库
user:当前用户
password('字符'):返回该字符的密码形式
md5('字符'):返回该字符的md5加密格式
控制函数:
①if(条件表达式,表达式1,表达式2):如果条件表达式成立,则执行表达式1,不然则执行表达式2
②case:情况1
case 变量或表达式或字段
when 常量1 then 值1
when 常量2 then 值2
……
else 值n
end
③case:情况2
case
when 条件1 then 值1
when 条件2 then 值2
……
else 值n
end
************************
####show variables like ‘%char%’
utf8编码的汉字一个汉字是3个字节,gbk编码的汉字一个汉字是2个字节,英文都是1个字节
#获取参数值的字节个数
SELECT
LENGTH( 'john' );
SELECT
LENGTH( '张三丰hahaha' );
#拼接字符串(用下划线拼接)
SELECT
CONCAT( last_name, '_', first_name )
FROM
employees;
SELECT
UPPER( 'john' );#变大写
SELECT
LOWER( 'JOHN' );#变小写
#示例:将姓变大写,名变小写,拼接
SELECT
CONCAT(
UPPER( last_name ),
LOWER( first_name )) AS 姓名
FROM
employees;
************************
#注意索引从1开始,下语句输出:
|out_put|
|和李四|
#截取从 指定索引处 后面 所有字符
SELECT
SUBSTR( '张三和李四', 3 ) out_put;
1 2 3 4 5
#截取从 指定索引处 指定字符长度的 字符
#下面语句输出:
|out_put|
|张三|
SELECT
SUBSTR( '张三和李四', 1, 2 ) out_put;
#案例:姓名中首字符大写,其他字符小写,用_拼接,显示出来
SELECT
CONCAT(
UPPER(
SUBSTR( last_name, 1, 1 )),
'_',
LOWER(
SUBSTR( last_name, 2 ))) output
FROM
employees;
************************
#返回 子串的 起始索引,找不到返回0
下例返回7
SELECT
INSTR( '杨不悔爱上了殷六侠', '殷六侠' ) AS out_put
1 2 3 4 5 67
************************
#6、trim 去掉首尾(空格不一定)
#输出 张翠山
SELECT
LENGTH(
TRIM( ' 张翠山 ' )) AS out_put;
#输出 张aaaa翠山
SELECT
TRIM( 'a' FROM 'aaaa张aaaa翠山aaaaaaaa' ) AS out_put;
************************
用 指定的字符 实现 左填充 指定长度,不够才填, 够了就保留
#输出*******殷素素
SELECT
LPAD( '殷素素', 10, '*' ) AS out_put;
#输出:殷素
SELECT
LPAD( '殷素素', 2, '*' ) AS out_put;
************************
用指定的字符实现右填充指定长度
#输出:殷素素ababababa
SELECT
RPAD( '殷素素', 12, 'ab' ) AS out_put;
************************
#9、replace 替换
SELECT REPLACE
( '张无忌爱上了周芷若', '周芷若', '赵敏' ) AS out_put;
四舍五入
SELECT
ROUND( 1.65 );#2
SELECT
ROUND(- 1.45 );#-1
SELECT
ROUND( 1.567, 2 );#1.57,小数点后保留2位
向上取整(返回>=该参数的最小整数)
SELECT
CEIL(- 1.02 );#-1
SELECT
CEIL( 1.00 );#1
SELECT
CEIL( 1.02 );#2
向下取整,返回<=该参数的最大整数
SELECT
FLOOR(- 9.99 );#-10
截断
SELECT TRUNCATE
( 1.65, 1 );#1.6;保留一位小数的意思
取余
#计算原理:
mod(a,b) : a - a/b * b
mod(-10,-3) : -10-(-10)/(-3)*(-3)=-1;
#举例:
SELECT MOD
( 10,- 3 );#1
返回当前系统日期加时间
SELECT
NOW();
返回当前系统日期,不包含时间
SELECT
CURDATE();
#curtime 返回当前时间,不包含日期
SELECT
CURTIME();
#可以获取指定的部分,年,月,日,小时,分,秒
SELECT YEAR
(
NOW()) AS 年;#2020
SELECT YEAR
( '1998-1-1' ) 年;#1998
SELECT YEAR
( hiredate ) 年
FROM
employees;#hiredate是表里的字段-入职时间
SELECT MONTH
(
NOW()) 月;
SELECT
MONTHNAME(
NOW()) 月;#显示英文月份
************************
将字符通过指定的格式转换成日期
%Y 四位的年份
%y 2位的年份
%m 月份 (01,02,...12)
%c 月份 (1,2,..., 12)
%d 日
%H 小时(24)%h(12)
%i 分钟 %s秒
SELECT
STR_TO_DATE( '9-13-1999', '%m-%d-%Y' ) 日期;#1999-09-13
字符串 日期格式
SELECT
STR_TO_DATE ('2020-4-17','%Y-%c-%d') AS output;#2020-4-17
字符串 日期格式
#查询入职日期为1992-4-3的员工信息
SELECT
*
FROM
employees
WHERE
hiredate = '1992-4-3';
#
SELECT
*
FROM
employees
WHERE
hiredate = STR_TO_DATE( '4-3 1992', '%c-%d %Y' );
第二块告诉电脑前面这块谁是日谁是月谁是年
************************
将日期转换成字符
SELECT
DATE_FORMAT( NOW(), '%y年%m月%d日' ) AS output;#20年4月17日
#查询有奖金的员工名和入职日期(xx月/xx日 xx年)
SELECT
last_name,
DATE_FORMAT( hiredate, '%m月/%d日 %Y年' ) 入职日期
FROM
employees
WHERE
commission_pct IS NOT NULL;
#使用较少
SELECT
VERSION();
SELECT
DATABASE();#查看当前库
SELECT
USER();
if else 的效果
SELECT IF(10>5,'大','小');
SELECT
last_name,
commission_pct,
IF
( commission_pct IS NULL, '呵呵,没奖金', '嘻嘻,有奖金' ) 备注
FROM
employees;
************************
switch case的效果
case 要判断的字段或表达式
when 常量1 then要显示的值1或语句1;
when 常量2 then要显示的值2或语句2;
...
else 要显示的值n或语句n
end
(搭配select当表达式,then加一个值,或者不搭配select当语句)
************************
部门号=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;
************************
#类似于多重if
case
when 条件1 then 要显示的值1或语句1
when 条件2 then 要显示的值2或语句2
...
else 要显示的值n或语句n
end
与上一种情况的不同就是case后不加表达式
************************
如果工资>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、sum,avg用于处理数值型
max,min,count可以处于任何类型
2、以上分组函数都忽略null值
3、可以和distinct搭配实现去重
4、count函数的单独介绍,一般用count(*)多,统计行数
5、和分组函数一同查询的字段要求是group by后的字段
************************
SELECT
SUM( salary )
FROM
employees;
SELECT
SUM( salary ) #和,ROUND(AVG(salary),2) #平均 FROM employees;
SELECT
MAX( salary ) #最高, MIN(salary) #最低 FROM employees;
SELECT
MIN( salary )
FROM
employees;
SELECT
COUNT( salary )
FROM
employees;
************************
SELECT
SUM( last_name ),
AVG( last_name )
FROM
employees;
SELECT
SUM( hiredate ),
AVG( hiredate )
FROM
employees;
#字符求和无意义,不建议这样用
#所以有的适合数值型数据,有的都适合。
SELECT
MAX( last_name ),
MIN( last_name )
FROM
employees;
SELECT
MAX( hiredate ),
MIN( hiredate )
FROM
employees;
#支持
SELECT
COUNT( last_name )
FROM
employees;#计算非空的值 107
SELECT
COUNT( commission_pct )
FROM
employees;#35
************************
#是的,忽略
SELECT
SUM( commission_pct ),
AVG( commission_pct )
FROM
employees;
************************
SELECT
SUM( DISTINCT salary ),
SUM( salary )
FROM
employees;
SELECT
COUNT( DISTINCT salary ),
COUNT( salary )
FROM
employees;
SELECT
COUNT( salary )
FROM
employees;
SELECT
COUNT(*)
FROM
employees;#统计每一列的数目,即所有行数,有一行里的一个不为NULL,就算上这一行
SELECT
COUNT( 1 )
FROM
employees;#和上一语句效果一样,加了一列全是1的列,里面可以任意给数字,给字符要加引号。
SELECT
AVG(salary),
employee_id
FROM employees;
#这个员工id查出来没有意义
语法:
select 分组函数(max,min这些),列(**要求出现在group by后面**)
from 表
[where 筛选条件]
group by 分组的列表
[order by]子句
注意:查询列表必须特殊,要求是分组函数和group by后出现的字段
特点:
1、分组查询中的筛选条件分为两类(筛选的数据源不同
数据源 位置 关键字
分组前筛选: 原始表 group by子句前面 where
分组后筛选:分组后的结果集 group by子句后面 having
①分组函数做条件,肯定是放在having子句中
②能用分组前筛选的,优先考虑用分组前筛选
2、group by子句支持单个字段分组,多个字段分组,
(多个字段之间用逗号隔开无顺序要求),表达式或函数(用的较少)
3、可添加排序(放在group by后)
************************
SELECT
MAX(salary),
job_id
FROM
employees
GROUP BY
job_id;
SELECT
COUNT(*),
location_id
FROM
departments
GROUP BY
location_id;
************************
SELECT
AVG( salary ),
department_id
FROM
employees
WHERE
email LIKE '%a%' #邮箱中包含a字符
GROUP BY
department_id;
SELECT
MAX( salary ),
manager_id
FROM
employees
WHERE
commission_pct IS NOT NULL
GROUP BY
manager_id;
************************
#①查询每个部门的员工个数
SELECT
COUNT(*),
department_id
FROM
employees
GROUP BY
department_id;
#②根据1的结果进行筛选
SELECT
COUNT(*),
department_id
FROM
employees
GROUP BY
department_id
HAVING
COUNT(*)> 2;#######重要##########
(#有点难)
#①查询每个工种有奖金的员工的最高工资
SELECT
MAX( salary ),
job_id
FROM
employees
WHERE
commission_pct IS NOT NULL
GROUP BY
job_id;
#②根据1的结果继续筛选,最高工资>12000
SELECT
MAX( salary ),
job_id
FROM
employees
WHERE
commission_pct IS NOT NULL
GROUP BY
job_id
HAVING
MAX( salary )> 12000;
#①查询领导编号>102的每个领导手下的最低工资
SELECT
MIN( salary ),
manager_id
FROM
employees
WHERE
manager_id > 102
GROUP BY
manager_id;
#②在1的基础上,最低工资>5000
SELECT
MIN( salary ),
manager_id
FROM
employees
WHERE
manager_id > 102
GROUP BY
manager_id
HAVING
MIN( salary )> 5000;
************************
#案例:按员工姓名的长度分组,查询每一组的员工个数,筛选员工个数>5的
SELECT
COUNT(*),
LENGTH( last_name ) len_name
FROM
employees
GROUP BY
len_name
HAVING
COUNT(*)> 5;
#案例:查询每个部门每个工种的员工的平均工资
SELECT
AVG( salary ),
department_id,
job_id
FROM
employees
GROUP BY
department_id,
job_id;
************************
##案例:查询每个部门每个工种的员工的平均工资,并将>10000的按高低排序
SELECT
AVG( salary ) a,
department_id,
job_id
FROM
employees
GROUP BY
department_id,
job_id
HAVING
a > 10000
ORDER BY
a DESC;
含义:
又称多表查询,当查询的字段来自多个表,就会用到连接查询
笛卡尔乘积现象:表1有m行,表2有n行,结果:m*n行
发生原因:没有有效的连接条件
如何避免:添加有效的连接条件
分类:
按年代分类:
sql92标准:仅仅支持内连接
sql99标准【推荐】:支持内连接 + 外连接(左外,右外)+ 交叉连接
按功能分类:
内连接:
等值连接,
非等值连接,
自连接
外连接:
左外连接,
右外连接,
全外连接
交叉连接
①多表等值连接的结果为多表的交集部分
②n表连接,至少需要n-1个连接条件
③多表的顺序无要求
④一般需要为表起别名
⑤可以搭配前面介绍的所有查询子句使用,比如排序,分组,筛选
SELECT NAME
,
boyName
FROM
boys,
beauty
WHERE
beauty.boyfriend_id = boys.id;
SELECT
last_name,
department_name
FROM
employees,
departments
WHERE
employees.department_id = departments.department_id;
************************
#2、为表起别名
①提高语句简洁度
②区分多个重名的字段
③如果为表起了 别名,则 查询的字段 就不能用 原来的表名 去限定,只能用 别名
SELECT
last_name,
e.job_id,
job_title
FROM
employees AS e,
jobs AS j #执行顺序是这句先
WHERE
e.job_id = j.job_id;
#两个表的顺序可以调换
SELECT
last_name,
e.job_id,
j.job_title
FROM
jobs AS j,
employees AS e
WHERE
e.job_id = j.job_id;
************************
#3、可以加筛选
SELECT
last_name,
department_name,
commission_pct
FROM
employees e,
departments d
WHERE
e.department_id = d.department_id
AND e.commission_pct IS NOT NULL;
SELECT
department_name,
city
FROM
departments d,
locations l
WHERE
d.location_id = l.location_id
AND city LIKE '_o%';
************************
#4、加分组
SELECT
COUNT(*) 个数,
city
FROM
departments d,
locations l
WHERE
d.location_id = l.location_id
GROUP BY
city;
SELECT
department_name,
d.manager_id,
MIN( salary )
FROM
departments d,
employees e
WHERE
d.department_id = e.department_id
AND commission_pct IS NOT NULL
GROUP BY
department_name;
************************
#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,
locations l
WHERE
e.department_id = d.department_id
AND d.location_id = l.location_id;
#####################################################
#创建工资级别
#运行下面这段代码,在数据库中创建一个job_grades表
CREATE TABLE job_grades
(grade_level VARCHAR(3),
lowest_sal INT,
highest_sal INT);
INSERT INTO job_grades
VALUES ('A',1000,2999);
INSERT INTO job_grades
VALUES ('B',3000,5999);
INSERT INTO job_grades
VALUES ('C',6000,9999);
INSERT INTO job_grades
VALUES ('D',10000,14999);
INSERT INTO job_grades
VALUES ('E',15000,24999);
INSERT INTO job_grades
VALUES ('F',25000,40000);
************************
案例:查询员工的工资和工资级别
SELECT
salary,
grade_level
FROM
employees e,
job_grades g
WHERE
salary BETWEEN g.`lowest_sal` #笔记1有说这里为什么要加引号?
AND g.`highest_sal`;
#有点像等值连接
#案例:查询员工名和上级的名称
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;
语法:
select 查询列表
from 表1 别名 【连接类型】
join 表2 别名 on 【连接条件】
on 连接条件
【where 筛选条件】
【group by 分组】
【having 筛选条件】
【order by 排序列表】
分类:
内连接:inner
外连接:
左外 left 【outer】
右外 right 【outer】
全外 full 【outer】
交叉连接:cross
************************
语法:
select 查询列表
from 表1 别名
inner join 表2 别名
on 连接条件;
分类:
等值
非等值
自连接
特点:
①添加排序、分组、筛选
②inner可以省略
③筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读
④inner join连接和sql92语法中的等值连接效果一样,都是查询多表的交集
************************
#案例1 查询员工名,部门名
SELECT
last_name,
department_name
FROM
employees e
INNER JOIN departments d ON e.department_id = d.department_id;
#案例2:查询名字中包含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:查询部门个数>3的城市名和部门个数(添加分组+筛选)
SELECT
city,
COUNT(*) 部门个数
FROM
locations l
INNER JOIN departments d ON d.location_id = l.location_id
GROUP BY
city
HAVING
COUNT(*)> 3;
#案例4:查询哪个部门的部门员工个数>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;
#案例5:查询员工名、部门名、工种名,并按部门名降序(三表连接)
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
d.department_name DESC;
************************
#案例1:查询员工的工资级别
SELECT
salary,
grade_level
FROM
employees e
INNER JOIN job_grades g ON e.salary BETWEEN g.lowest_sal
AND g.highest_sal;
#案例2:查询工资的个数>20的级别个数,并且按工资级别降序
SELECT
salary,
grade_level,
COUNT(*)
FROM
employees e
INNER 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;
************************
#案例1:查询员工的名字,上级的名字
SELECT
e.last_name,
m.last_name
FROM
employees e
JOIN employees m ON e.manager_id = m.employee_id;
#加筛选:姓名中包含字符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%';
************************
#有主从表,主表就是你要查的信息主要来自的表
应用场景:
用于查找一个表中有,另一个表中没有的记录
特点:
1、外连接的 查询结果 为主表中 所有的记录
如果 从表中 有和它 匹配的,则显示 匹配的值
如果 从表中 没有和它 匹配的,则显示 null
外连接查询结果 = 内连接结果 + 主表中有 而从表中没有的 记录
2、左外连接:left jon左边的是主表
右外连接:right join右边的是主表
3、左外和右外交换两个表的顺序,可以实现同样的效果
4、全外连接(不支持) = 内连接结果 + 表1有 但表2没有 + 表2有 但表1没有
(结果里没有的都是null)
#左外连接
SELECT
be.NAME,
bo.*
FROM
beauty be #主表
LEFT OUTER JOIN boys bo ON be.boyfriend_id = bo.id;
#右外连接
SELECT
be.NAME,
bo.*
FROM
boys bo #从表
RIGHT OUTER JOIN beauty be ON be.boyfriend_id = bo.id
WHERE
bo.id IS NOT 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;
************************
SELECT
be.*,
bo.*
FROM
beauty be
CROSS JOIN boys bo;
##建议使用sql99语法
看两个图片意会一下:
最好是在写之前,能过一眼数据,感受一下大概是要取什么,取出来大概是什么样子。
#可能是最难的查询
含义:出现在 其他语句内部的 select语句,称为 子查询 或 内查询
外部的 查询语句,称为 主查询 或 外查询
分类:
1. 按子查询出现的位置:
select后面: 仅仅支持 标量子查询
from后面: 支持 表子查询
☆ where或者having后面:标量子查询,列子查询,行子查询
exists后面(相关子查询):表子查询
2. 按结果集的行列数不同:
标量子查询(结果集只有一行一列)
列子查询(结果集只有一列多行)
行子查询(结果集有一行多列)
表子查询(结果集一般为多行多列)
************************
#1、标量子查询
#2、列子查询(多行子查询)
#3、行子查询(多行多列)
特点:
①子查询放在小括号内
②子查询一般放在条件右侧
③标量子查询,一般搭配单行操作符使用
> < >= <= = <>
列子查询一般搭配多行操作符使用
IN/NOT IN、ANY/SOME、ALL
任意一个 某一个 所有
④子查询的执行优先于主查询执行
************************
#案例1:谁的工资比Abel高
#①查询abel的工资
SELECT salary
FROM employees
WHERE last_name='Abel';
#②查询员工的信息,满足salary>①的结果
SELECT *
FROM employees
WHERE salary>(
SELECT salary
FROM employees
WHERE last_name='Abel'
);
#案例2:返回job_id与141号员工相同,salary比143号员工多的员工姓名,job_id和工资
#①查询141号员工的job_id
SELECT
job_id
FROM
employees
WHERE
employee_id=141;
#②查询143号员工的salary
SELECT
salary
FROM
employees
WHERE
employee_id=143;
#③员工的姓名,job_id,工资,要求job_id=①并且salary>②
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
);
#案例3:返回公司工资最少的员工的last_name,job_id,salary
#①查询公司的最低工资
SELECT
MIN(salary)
FROM
employees
#②查询last_name,job_id
SELECT
last_name,
job_id,
salary
FROM
employees
WHERE
salary = ( SELECT MIN( salary ) FROM employees );
#案例4:查询最低工资大于50号部门的最低工资的部门id和其最低工资
#①查询50号部门的最低工资
SELECT
MIN( salary )
FROM
employees
WHERE
department_id = 50;
#②查询每个部门的最低工资
SELECT
MIN( salary )
FROM
employees
GROUP BY
department_id;
#③筛选②
SELECT
MIN( salary ),
department_id
FROM
employees
GROUP BY
department_id
HAVING
MIN( salary ) > ( SELECT MIN( salary ) FROM employees WHERE department_id = 50 );
************************
#案例1:返回location_id是1400或1700的部门中所有员工姓名
**法一:**
#①查询location_id是1400或1700的部门编号
SELECT DISTINCT
department_id
FROM
departments
WHERE
location_id IN(1400,1700);
#②查询员工姓名要求部门号是①中的某个
SELECT
last_name
FROM
employees
WHERE
department_id IN ( SELECT DISTINCT department_id FROM departments WHERE location_id IN ( 1400, 1700 ) );#in可以换成 =ANY
#我真的搞不懂navicat这个美化为什么这里是一整行,不如老师的sqlyog好看呢
**法二:**
SELECT
last_name
FROM
employees e
LEFT JOIN departments d ON e.department_id = d.department_id
WHERE
d.location_id IN ( 1400, 1700 );
#in与(= ANY)、not in与 (<>ALL)
#为什么不用连接查询?因为子查询效率更高
************************
#案例2:返回其他工种中比job_id为‘IT_PROG'的任一工资低的员工信息
#这题的题意不太好理解哈
#用any
SELECT
employee_id,
last_name,
job_id,
salary
FROM
employees
WHERE
salary < ANY ( SELECT DISTINCT salary FROM employees WHERE job_id = 'IT_PROG' )
AND job_id <> 'IT_PROG';
#案例3:返回其他工种中比job_id为‘IT_PROG'的所有工资低的员工信息
SELECT
employee_id,
last_name,
job_id,
salary
FROM
employees
WHERE
salary < ALL ( SELECT DISTINCT salary FROM employees WHERE job_id = 'IT_PROG' )
AND job_id <> 'IT_PROG';
************************
#用的较少
#案例:查询员工编号最小并且工资最高的员工信息
SELECT
*
FROM
employees
WHERE
employee_id = ( SELECT MIN( employee_id ) FROM employees )
AND salary = ( SELECT MAX( salary ) FROM employees );
#或者
SELECT
*
FROM
employees
WHERE
( employee_id, salary ) = ( SELECT MIN( employee_id ), MAX( salary ) FROM employees );
仅支持标量子查询 一行一列的
#案例1:查询每个部门的员工个数
#我第一时间会用连接 + 分组 做
SELECT
d.*,
( SELECT COUNT(*) FROM employees e WHERE e.department_id = d.department_id ) 个数
FROM
departments d;
#子查询真的是..又回到被SAS支配中了
#案例2:查询员工号=102的部门名
SELECT
( SELECT department_name FROM departments d INNER JOIN employees e ON d.department_id = e.department_id WHERE e.employee_id = 102 );
#这题的答案真是强行嵌套..穿着雨衣打伞啊,我傻了
#往后我不去理解了,明明可以内联,我都快傻了,跳过!
#这美化的是美化了个锤子,又是一行
#案例:查询每个部门的平均工资的工资等级
#①查询每个部门的平均工资
SELECT
AVG(salary),
department_id
FROM
employees
GROUP BY
department_id;
#②连接①的结果集和等级表,筛选条件 平均工资between最低和最高
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 g.lowest_sal
AND g.highest_sal;
exists完整的查询语句
结果:1或0
SELECT EXISTS
(
SELECT
employee_id
FROM
employees)#结果为1,表示存在
#案例1:查询有员工的部门名
SELECT
department_name
FROM
departments d
WHERE
d.`department_id` IN ( SELECT department_id FROM employees );
#或
SELECT
department_name
FROM
departments d
WHERE
EXISTS ( SELECT * FROM employees e WHERE e.department_id = d.department_id );
#案例2:查询没有女朋友的男生信息
#in
SELECT
bo.*
FROM
boys bo
WHERE
bo.id NOT IN ( SELECT boyfriend_id FROM beauty );#exists
SELECT
bo.*
FROM
boys bo
WHERE
NOT EXISTS ( SELECT boyfriend_id FROM beauty be WHERE bo.id = be.boyfriend_id );
应用场景:当要显示的数据一页显示不全,需要分页提交sql请求
语法:
select 查询列表
from 表
{join type join 表2
where 筛选条件
group by 分组字段
having 分组后的筛选
order by 排序的字段}
limit offset,size;
参数 参数
offset:要显示条目的起始索引,起始索引从0开始
size:要显示的条目数
特点:
①limit语句放在查询语句的**最后**
②公式
要显示的页数page,每页的条目数size
select 查询列表
from 表
limit (page-1)*size,size;
size = 10
page
1 0
2 10
3 20
SELECT
*
FROM
employees
LIMIT 0,
5;
SELECT
*
FROM
employees
LIMIT 5;
#
SELECT
*
FROM
employees
LIMIT 10,
15;#索引从0开始 #索引从0开始
SELECT
*
FROM
employees
WHERE
commission_pct IS NOT NULL
ORDER BY
salary DESC
LIMIT 10;
union 联合 合并
语法:
查询语句1
union
查询语句2
union
……
应用场景:
要查询的结果来自于多个表,且多个表没有直接的连接关系,但查询的信息一致时
特点:
1. 要求多条查询语句的查询列数是一致的
2. 要求多条查询语句的查询的每一列的类型和顺序最好一致
3. 用union会自动去重,不想去重的话就用union all
SELECT
*
FROM
employees
WHERE
email LIKE '%a%'
OR department_id > 90;
#用union
SELECT
*
FROM
employees
WHERE
email LIKE '%a%' UNION
SELECT
*
FROM
employees
WHERE
department_id > 90;
#上面这个例子看不出来union的意义哈,我看着还怪麻烦
#我是sql8.0没test这个库,不过看看代码也能明白他想干啥
SELECT
id,
cname,
csex
FROM
t_ca
WHERE
csex = "男" UNION
SELECT
t_id,
tName,
tGender
FROM
t_ua
WHERE
tGender = 'male';
#不好意思我懂了,union的好处是当你一个库里 好几个表之间 没有那种可以建立连接的关系,用这个就太方便了
#上面这个例子啊,两个表的字段不一样,但是意义却一样,如果内容不一样的话,合不起来