MySQL数据库--DQL语言

MYSQL

一、为什么要学数据库

保存数据的容器:

​ 数组 (存到内存中)

​ 集合 (存到内存中)

​ 文件(存没问题,但是不太适合查询)

​ 故需要一套管理系统去管理里边的数据

数据库的好处:

  • 实现数据持久化
  • 使用完整的管理系统统一管理,易于查询

数据库的相关概念:

​ DB: database 存储数据的仓库,保存了一系列有组织的数据(Mysql,Oracle贵,DB2,SQLServer(只能在windows下))

​ DBMS:Database management system 数据库管理系统,用于管理db中的数据,数据库是通过dbms创建和操作的容器

​ 多台客户端—》数据库管理系统----》多个数据库

​ SQL:结构化查询语言,专门用来与数据库通讯的语言,几乎所有DBMS都支持SQL,简单易学,灵活使用可以进行非常复杂和高级的数据库操作。

DBMS分为两类:

  • 基于共享文件系统的DBMS(access)
  • 基于CS架构(客户端服务端)的DBMS(mysql,Oracle,SqlServer)

[mysqld] 服务端配置

port=3306

basedir = ‘…’ 表示安装目录

datadir = ‘…’ 表示文件目录

character-set-server = utf8 字符集

default-storage-engine=INNODB 数据库引擎

max_connetions = 100 最大连接数

修改完配置后需要重启

mysql服务的启动和停止

windows

​ 停止服务 net stop mysql

​ 启动服务 net start mysql

linux

​ 停止服务 service mysqld stop

​ 启动服务 service mysqld start

mysql -h localhost -P 3306 -u root -pmysql 这里输入密码是不可以有空格,其他参数有无都行

exit 退出

mysql常见命令

show databases; 查看数据库

​ information_schema 保持元数据信息

​ performance_schema 性能信息

​ test 测试数据库

​ mysql 保存用户信息

use test 进入库

​ source sql文件路径;导入目标数据库,路径可以直接拖拽sql文件到黑窗口获得。

​ show tables 查看库下表

​ show tables from mysql 查看所写库下表

select database()  查看当前所在库

​ create table student(id int,name varchar(20)); 创建表

​ desc student 查看表结构

​ select * from student 查看表中数据

​ insert into student (id,name) values(2,‘mingzhe’); 向表中插入数据

​ update student set name=‘lilei’ where id = 1 修改数据

​ delete from student where id = 2;删除数据

select version() 查看数据库版本

在命令行界面中 mysql --version 查看版本

在命令行界面中 mysql --V 查看版本

mysql语法规范

  1. 不区分大小写,建议关键字大写,表面列明小写
  2. 每条命令用;结尾
  3. 每条命令根据需求可以进行缩进,换行,建议关键字单独一行。
  4. 注释,用于解释说明
    1. 单行注释 # 注释文字
    2. 单行注释 – 注释文字 注意有空格
    3. 多行注释 /* 注释文字 */

DQL语言学习

​ data query languge数据查询语言 查

基础查询

查询表中单个字段

​ select 查询列表 from 表名

​ 查询列表可以是:表中字段,常亮,表达式,函数

​ 查询结果是一个虚拟的表格

​ select id from apple;

查询表中多个字段

​ select 字段一,字段二,… from 表名

​ 查询字段顺序和个数都可以和原表不一致,个数和顺序按需求

​ select id,name from apple;

查询表中所有字段

​ select * from 表名

​ * 代表的是所有的字段,顺序和源试表一样。

​ 若想通读写更好,更加灵活,则拼写全字段查询。

​ select * from apple;

查询时细节补充

​ 1.查询时要打开指定的库

​ 2.当字段被当成关键字时,使用 ‘’ 着重符来增加可读性

​ 3.Navicat选中所选语句,可以部分执行

查询常量值

​ select 常量值:

​ 常量值不来自于某表故不用from

​ 显示字段名为其本身

​ select 100;

​ select ‘john’;

​ select 表达式:

​ select 100*98;

​ select 函数:

​ select varsion();

为字段起别名

​ select 字段 as 别名 from 表名:

​ 方便理解,增加可读性

​ 若查询字段有重名情况,则起别名可以区分开来

​ select id as 序号,name as 姓名 from apple

​ select 字段 别名 from 表名:

​ as 可以省略

​ 若别名有特殊符号空格 #等,则需给别名加上双引号

​ select id 序号,name 姓名 from apple

字段去重

​ select distinct 字段 from 表名:

​ select distinct name from apple;

+号的作用

​ select 值一+值二 ;

​ mysql的+号只有一个功能,就是运算符

​ select 100 + 90; 若俩操作值都为数值型,则做加法运算

​ select ‘123’ +90;若一方为字符型,试图转换为数值型,成功则运算

​ selecr ‘abc’ + 90; 失败则字符串为0,在运算

​ select null + 90; 只要一方为null,则结果为null

	select 'null' + 90 ; 结果为90
CONCAT实现拼接

​ select concat(‘字符一’,‘字符二’,‘字符三’) as 结果:

​ select concat(‘id’,‘name’) as ‘信息’ from apple;结果全为 idname

​ select concat(id,name) as ‘信息’ from apple; 结果为两字段拼接

IFNUll判断是否为空

​ select IFNULL(字段,为空所设值) 新字段名;

​ 为空监测,为空了则替换为其所设值

​ select IFNULL(name,‘default’) as new_name from apple;

条件查询

WHERE语法

​ select 查询列表 from 表名 where 筛选条件;

​ 执行顺序:from先查看有无表名,在where进行筛选,select在选择字段

条件表达式筛选

​ 条件运算符 < > = != <> >= <=

​ <> 和 != 都为不等于,最好按<>使用

​ 查询id>1的人: select * from apple where id >1;

逻辑表达式筛选

​ 逻辑运算符 && || ! and or not

​ 主要作用就是为了连接条件表达式

​ &&和and :俩都满足则满足

​ ||和or:一个满足则满足

​ !和not:取反情况

​ case1:查询id在1到3之间的人:select id,name from apple where id >=1 and id <= 3;

​ case2:查询id不是在90到100之间的,或者工资高于15000的员工:

​ select last_namr from employees where id<=90 or id >= 100 or salary >= 15000;

​ select last_namr from employees where not(id>=90 and id <= 100) or salary >= 15000;

模糊查询

like

​ 一般和通配符搭配使用

​ %表示任意多个字符,包含零个字符

​ _表示任意单个字符

​ \转义符当通配符出现在查询条件中使用

​ escape 指定转移字符

​ case1:查询名字包含a的:

​ select name from apple where name like ‘%a%’;

​ case2:查询二字符为a,五字符为b的:

​ select name from apple where name like “_a__b”

​ case3:查询一字符为_的:

​ select name from apple where name like “\_*”

​ select name from apple where name like “_a%” escape ‘a’;

between and

​ 包含临界值

​ 前后临界值大小顺序不能变,调换后不报错,但没数据。

​ 提高语句简洁度

​ case1:查询id在3-5之间的

​ select name from apple where id between 3 and 5;

in

​ 用于判断某值是否属于列表中某一项

​ in列表的值类型必须一致或兼容(“123”可以转为整性,与数值性兼容)

​ 不可以使用通配符,in等价于 =号,而不是like

​ case1 :查询员工的工种编号是 IT_PROG,AD_VP,AD_PERS中的一个员工名和工种编号

​ select * from emploees where job_id in(‘IT_PROG’,‘AD_VP’,‘AD_PERS’)

is (not) null

​ =不可以判断null值

​ case1:没有奖金的员工

​ select * from employees where commission_pct is null;

​ case2:有奖金的员工

​ select * from employees where commission_pct is not null;

安全等于

​ <=> 可以判断普通类型的值, 也可以去判断null值

​ 代表的是判断是否等于,但是可读性比较差。

作业

case1:工资大于12000的姓名和工资

​ SECELT name,salary FROM employees WHERE salary >= 12000;

case2:员工号为176的员工的姓名和部门号和年薪

​ SELECT name,depatment_id,(salary +IFNULL(goal,0) )*12 as money from employees WHERE id = 176;

case3:选择工资不在5000-12000的姓名和工资

​ SELECT name,salary FROM employees WHERE salary not between 5000 and 12000;

case4:选择20或50号部门工作的员工姓名和部门号

​ SELECT name,depatment_id FROM depatment_id in(20,50);

case5:选择公司中没有管理者的员工姓名和部门号

​ SELECT name,depatment_id FROM manage IS NULL;

case6:选择公司中有奖金的员工姓名,工资和奖金级别

​ SELECT name,salary,rank FROM employees WHERE goal IS NOT NULL;

case7:选择员工名字第三个字母是a的员工姓名

​ SELECT name FROM eployees WHERE name like “__a%”;

case8:选择姓名中有字母a和e的员工姓名

​ SELECT name FROM eployees WHERE name like “%a%” and name like “%e%”;

case9:选择姓名中以字母e结尾的员工姓名

​ SELECT name FROM eployees WHERE name like “%e”;

case10:选择部门编号为80-100之间的员工姓名

​ SELECT name FROM eployees WHERE depatment_id betweend 80 and 100;

case11:选择managet_id 是100 101 110的员工信息

​ SELECT name FROM eployees WHERE dmanaget_id in(100,101,110);

cass12:

​ SELECT IFNULL(id,0) from employees WHERE id = 1000;

​ 若此时则显示为空

​ 但是

​ SELECT IFNULL((select id from employess where id = 1000),0)

​ 此时为零

排序查询

语法

​ select 字段 from 表名 (where 条件) order by 字段一 (asc/desc),字段二 (asc/desc);

​ 默认为asc升序,desc为降序

​ order by支持单字段,多字段,表达式,函数,别名

​ order by 一般放在查新语句的最后面,limit除外;

​ 执行顺序: from where select order by

​ case 1 工资升序

​ SELECT name,salary FROM employees ORDER BY salary ASC;

​ case2 部门编号大于90的入职时间先后

​ SELECT name,time FROM employees WHERE depatment_id >= 90 ORDER BY time ASC;

​ case3 按年薪的高低显示元的信息和年薪,表达式

​ SELECT *,salary * 12 * (1+IFNULL(commission_pct,0)) as monny from employees order by salary * 12 * (1+IFNULL(commission_pct,0)) DESC;

​ SELECT *,salary * 12 * (1+IFNULL(commission_pct,0)) as monny from employees order by monny DESC; 按别名排序

​ case 4:按姓名长度来排序,函数length()

​ SELECT * from employess order by length(name) desc;

​ case5 查询信息,先工资后编号,多字段排序

​ select *from employees order by salary ,id;

常用函数

功能:

​ 将实现某个功能的一组逻辑语句,封装到方法中,对外暴露一个公开的名字

好处:

​ 隐藏了了实现细节

​ 提高了代码重用性

调用:

​ select 函数名(实参列表 ) from 表; 若函数用到了表中的字段,则需要加表

特点:

​ 叫什么,函数名

​ 干什么,函数功能

分类:

​ 单行函数:传过一个参数,经过处理,最终会有一个返回值

​ 分组函数:做统计使用的,传进去一组值,返回其统计聚合数据。

单行函数:

字符函数:

length():

​ 获取值的长度

​ SELECT LENGTH(‘john’)

​ SELECT LENGTH(“张三丰”) utf8一个中文三个字节,gbk两个字节

concat():

​ 拼接字符串

​ SELECT CONCAT(last_name,’_’,frist_name) 姓名 FROM employees;

upper(),lower():

​ 对字符进行大小写

​ select upper(“aaa”);把字符进行大写

​ select lower(“AAA”);把字符进行小写

​ case1: 姓大写,名小写,拼接

​ SELECT concat(upper(first_name),’_’,lower(last_name)) ‘姓名’ from employees

substr(),substring():

​ 重载:名字一样,参数列表不一样

​ 截取字符串,索引从1开始

​ select substr(“李莫愁爱上了陆展元”,7) as out_put; 截取指定索引后面所有字段

​ select substr(“李莫愁爱上了陆展元”,1,3) as out_put; 截取制定索引出制定长度的字符

​ case2:姓名字首字母大写, 其他小写

​ SELECT CONCAT(UPPER(SUBSTR(first_name),1,1),’_’,lower(first_name,2)) out_put from employees;

instr():

​ 返回第一个所选字符串出现的下标位置,若找不到则为0

​ select instr(“杨不悔爱上了殷梨亭”,“殷梨亭”) as out_put;

trim():

​ 去除首尾空格

​ select trim(" 张翠山 ") as out_put;

​ 去除首尾的固定字符

​ select trim(“a” from “aaaa张aaaa翠山aaaa”) as out_put;

lpad():

​ 用指定的字符实现左填充指定的长度,若超过了则弃右截断。

​ select lpad(“殷素素”,10,“*”) as out_put;

rpad():

​ 同上

replace():

​ 替换字符串,满足条件则全部替换s

​ select replace(“张无忌爱上了周芷若和周芷若”,“周芷若”,”赵敏“) as out_put;

数学函数:

round():

​ 四舍五入,取绝对值后四舍五入在加上符号

​ select round(1.45);

​ 小数点后保留两位

​ select round(1.55,2);

ceil():

​ 向上取整,返回>= 该参数的最小整数

​ selecr ceil(1.00);

​ selecr ceil(0.1);

floor():

​ 向下取整,返回<=该参数的最大整数

​ select floor(-9.99);

truncate():

​ 截断,后边不管是什么都不要了

​ select truncate(1.65,1); 小数点后保留一位,其余都不要

mod():

​ 取余和10%3差不多。

​ select MOD(10,3);

日期函数:

now():

​ 返回当前系统日期和时间

​ select now():

curdate():

​ 返回当前系统日期,不包含时间

​ select curdate():

curtime():

​ 返回当前时间,不包含日期

​ select curtime();

year(),month(),…:

​ 获得指定的部分,年月日等…

​ select year(now());

​ select year(‘1989-1-2’);

​ select year(hiredate) 年 from employees;

​ 显示月份的英文

​ select monthname(now());

str_to_date():

​ 将日期格式的字符转换为指定格式的日期

​ 当日期格式不是按照年月日排列的时候,就需要转换。

​ 如 4-3 1997

​ select str_to_date(“4-3 1997”,"%c-%d %Y") as date;

date_format():

​ 将日期转换为字符

​ 当要求日期格式为3月/4日 2017年时时。

​ select date_format(“2017-03-04”,"%c月/%d日 %Y年") as date;

datediff():

​ 将前面的日期减去后边的日期

​ select datediff(date1,date2);

其他函数:

select varsion():

​ 查看版本号

select database():

​ 查看当前数据库

select user():

​ 查看当前用户

流程控制函数:

if ():

​ 条件成立,返回二号位的值,反之返回三号位的值。

​ select IF(10<5,‘大’,‘小’);

​ select id,if(name is null,“没有名字”,“有名字”) from apple;

case():

​ 处理等值判断

​ case 要判断的字段或表达式

​ when 常量一 then 要显示的值1或语句一

​ when 常量二 then 要显示的值1或语句二

​ …

​ else 要显示的值n或语句n;

​ end

​ case1:若部门为20,则为1.2倍,部门为30,则为1.3倍,为40,则为1.4倍。其他还是原值。

​ 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 new_salary

​ from employees;

​ 条件判断

​ case

​ when 条件一 then 要显示的值1或语句一

​ when 条件二 then 要显示的值1或语句二

​ …

​ else 要显示的值n或语句n;

​ end

​ case2:若工资>1w,显示A,工资>2w,显示B,工资>3w,显示C

​ select

​ case

​ when salary > 10000 then ‘A’

​ when salary >20000 then “B”

​ when salary > 30000 then “c”

​ else “D” end as “rank” from employees;

​ 这里rank为关键字,要加引号。

分组函数:

介绍:

​ 功能:用作统计使用,又称为聚合函数或统计函数或组函数

​ 分类:

​ sum 求和

​ avg 平均值

​ min 最小值

​ max 最大值

​ count 计算个数

​ 语法:

​ select sum(id) from apple;

​ 特点:

​ 1.聚合函数返回值为每一个字段一个值

​ 2.sum,avg一般用于处理数值型,max,min,count可以处理任意类型(因为字符串可以排序,所以可以有最大值最小值)

​ 3.以上分组函数都忽略null值

​ 4.可以和distinct搭配实现去重运算。

​ select sum(distinct salary),sum(salary) from employees;

​ select count(distinct salary),count(salary) from employees;

​ 5.count函数的单独介绍

​ select count(*) from emploees; 用来统计总行数

​ select count(1) from emploees; 相当于加了一列1的值,从而统计1的个数来得出行数

​ 效率:

​ myisam 存储引擎下,count(*) 的效率高

​ innodb 存储引擎下,count(*) 和count(1)性能差不多 比count(字段) 要高一些,因为字段要有一个判断为null的操作。

​ 6.和分组函数一同查询的字段有限制

​ 若字段和分组函数一起用,分组函数一个结果,而字段多个结果,得出结果集不是规则表格,则会报错。

​ 一般要求是group by 后的字段。

分组查询:

特点:

​ 语法:

​ select 分组函数,列(要求出现在group by的后面) from 表 【where筛选条件】 group by 分组列表 【order by 子句】

​ 查询列表必须特殊,要求是分组函数group by之后出现的字段

​ 分组前筛选:数据源是原始表,where放在分组组调研的前面

​ 分组后筛选:数据源是分组后的结果集,having放在分组字段的后面

​ 分组函数做筛选条件,肯定放在having

​ 能用分组前筛选的,就优先考虑放在分组前。

​ group by 子句支持单个字段分组,多个字段分组,分组字段的顺序没有要求。也支持表达式和函数,但是用的较少,也可以添加排序,order by放在语句最后(order by可以使用别名)。

group by:

​ 可以将表中的数据分成若干个小组

​ case1:每个工种的最高工资:

​ select max(salary),job_id from employees group by job_id order by salary desc;

​ case2:查询每个位置上的部门个数:

​ select count(*),location_id from departments group by location_id;

​ #添加筛选条件

​ case3:查询邮箱中包含a字符的,每个部门的平均工资

​ select avg(salary),department_id from employees where email like “%a%” group by department_id;

​ case4:查询有奖金的每个领导手下员工的最高工资

​ select max(salary),manager_id from employees where commission_pct is not null group by manager_id;

​ #添加复杂的筛选条件
​ 单句的sql中的where是对单条信息的筛选,若想对组进行筛选,则在查询结果上进行再次查询即可。

​ case5:查询哪个部门的员工大于2

​ select count_1,de from (select department_id as de,count(*) as count_1 from employees group by department_id) as b where count_1 >2;

​ 这里临时表必须有一个自己的名字

having:

​ 对分组后的数据进行筛选

​ select count(*),department_id from employees group by department_id having count(*) >2;

​ case6:插叙每个工种有奖金的员工的最高工资>12000的工种编号和最高工资

​ select max(salary),job_id from employees where commission_pct is not null group by job_id having max(salary) >12000;

​ case7:查询领导编号>102 的每个领导手下的最低工资>5000 的领导编号是哪个 以及最低工资

​ select min(salary),manager_id from employees where manager_id >102 group by manager_id having min(salary) >5000;

按表达式/函数分组:

​ case 1;按员工的姓名长度分组,查询每一组的员工个数,筛选员工个数>5的有哪些?

​ select count(*),length(last_name) from employees group by length(last_name) having count(*) >5;

​ group by 和 having都支持别名,但是where不支持

​ select count(*) c1,length(last_name) l1 from employees group by l1 having c1 >5;

按多个字段分组:

​ case1:查询每个部门每个工中的员工的平均工资

​ select avg(salary),department_id,job_id from employees group by department_id,job_id;

分组排序:

​ order by可以用别名。

​ case1:查询每个部门每个工中的员工的平均工资,并按平均工资高低显示。

​ select avg(salary),department_id,job_id from employees group by department_id,job_id order by avg(salary) desc;

习题:

​ case1:查询最大和最小工资的差值:

​ select max(salary)-min(salary) diffrence from employees;

连接查询

介绍:

含义:

​ 又称多表查询,当查询字段来自于多个表时,就会用到。

​ select name,boyname from boys,beauty;

​ 拿第一张表的每个记录挨个匹配第二张的每一条数据。笛卡尔乘积现象。

​ 造成原因就是没有加任何连接条件。添加有效连接条件去避免。

​ select name,boyname from boys,beauty where beauty.boyfriend_id = boys.id;

​ 分类:

​ 按年代分类

​ sql92标准,仅仅支持内连

​ sql99标准(推荐),支持内连接+外连接(左外和右外)+交叉连接

​ 按功能分类

​ 内连接

​ 等值连接

​ 非等值连接

​ 自连接

​ 外连接

​ 左外连接

​ 右外连接

​ 全外连接

​ 交叉连接

SQL92标准

等值连接

特点:

​ 多表等值连接的结果为多表的交集部分

​ n表连接,至少需要n-1个条件

​ 多表的顺序没有要求

​ 一般为表起别名

​ 可以搭配前面介绍的所有子句使用,比如:排序,分组等

​ 拿第一张表的每一行,去匹配第二张表的每一行,拿匹配条件进行过滤。

​ case1:查询女生和对应男生名字

​ select name,boyname from boys,beauty where beauty.boyfriend_id = boys.id;

​ case2: 查询员工名和对应的部门名

​ select first_name,department_name from employees,departments where employees.department_id = departments.department_id;

​ case3:查询工种号,员工名,工种名

​ select first_name,jobs.job_id,job_title from employees,jobs where employees.job_id = jobs.job_id;

​ 若job_id之间不加表名,则会 报ambigous;,表示有歧义,若给表起了别名,则查询字段不能使用原来的表名去限

​ 在连接查询,可以为表起别名,提高语言简介度,

​ 这两个表的顺序是可以调换的,不管拿谁匹配谁,只要满足条件就可以。

​ 使用等值连接的连接条件,结果得出是两个表的交际。

加筛选:

​ case1:查询有奖金的员工名,部门名

​ select last_name,department_name from employees ,departments where commission_pct is not null and employees.department_id = departments.department_id;

​ case2:查询城市名中第二个字符为o,对应的部门吗和城市名

​ select lo.city,de.department_name from locations lo,departments de where de.department_name like “_o%” and lo.location_id = de.location_id;

加分组:

​ case3:查询每个城市的部门个数

​ select city,count(*) as d_m from departments d,locations l where l.location_id = d.location_id group by city;

​ case4:插叙有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资

​ select min(salary),d.department_name,d.manager_id from departments d,employees e where e.department_id = d.department_id and commission_pct is not null group by d.department_id,d.manager_id;

​ 我们要查询两个列,但是又不确定这两个列是一一对应的。分组的时候把两个列都加上。

加排序:

​ case5:查询每个工种的工种名和员工的个数,并且按员工的个数降序

​ select count(*),job_title from jobs j,employees e where e.job_id = j.job_id group by j.job_title order by count(*) desc;

三表连接:

​ case6:查询员工名,部门名和所在的城市

​ select first_name,department_name,city from employees e,locations l ,departments d where d.location_id = l.location_id and e.department_id = d.department_id and city like “s%”;

非等值连接:

​ 在等值连接的基础上,连接条件中不为等于号。

​ case1:查询员工的工资和工资级别

​ select grade_level,salary from employees e,job_grades g where e.salary between g.lowest_sal and g.highest_sal;

自连接:

​ 相当于等值连接,自己连接自己,不是任何表都可以做,除非里边有一些特殊的字段。

​ case1:查询员工名和上级的名称

​ select a.last_name,a.employee_id, a.manager_id,b.last_name as ling,b.employee_id as dao from employees a,employees b where a.manager_id = b.employee_id;

作业:

​ case1:显示员工表的最大工资,工资平均值

​ select max(salary),avg(salary) from employees;

​ case2:查询员工表的employee-id,job_id,last_name,那department_id降序,salary升序。

​ select employee_id,job_id,last_name from employees order by department_id desc,salary;

​ case3:查询原表的job_id有包含 a.e的并且a,在e的前面

​ select job_id from employees where job_id like “%a%e%”;

​ case4:显示当前日期,以及去除前后空格,截取子字符串的函数。

​ select now();

​ select trim(" aaa ");

​ select trim(字符 from " ");

​ select substr(“abcd”,2,3);

SQL99标准

语法:

​ select 查询列表 from 表 别名 【连接类型】 join 表2 别名 on 连接条件 【where 筛选条件】…

​ 吧连接条件和筛选条件分离,提高可读性。

内连接

​ 特点:添加排序,分组,筛选

​ inner可以省略

​ 筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读。、

​ inner join 和92语法中的等值语法效果是一样的,都是查询多表的交集。

inner:

​ 语法:select 查询列表 from 表 别名 inner join 表2 别名 on 连接条件 【where 筛选条件】…

等值连接:

​ case1:查询员工名,部门名

​ select last_name,department_name from employees e inner join departments d on e.department_id = d.department_id;

​ 此时调换两个表的数据时,发现还是可以的

​ # 添加筛选

​ case 2:查询名字中包含a的员工名和工种名

​ select job_title,last_name from employees e inner join jobs j on j.job_id = e.job_id where e.last_name like “%a%”;

​ # 添加分组和筛选

​ case3:查询部门个数>3的城市名和部门个数

​ select city,count(*) from locations l inner join departments d on d.location_id = l.location_id group by city having count(*)>3;

​ #排序

​ case4:查询哪个部门的部门员工个数>3的部门名和员工个数,并按个数降序

​ select count(*),department_name from employees e inner join departments d on d.department_id = e.department_id group by department_name having count(*) >3 order by count(*) desc;

​ # 三表连接

​ case5:查询员工名,部门名,工种名,并那部门名降序

​ 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 job_title desc;

​ n表连接至少需要n-1个连接条件,当多表连接时。

​ 一个连接条件跟着一个 连接。

​ 顺序的要求:保证后边的表能与之前的表满足连接条件。

非等值连接:

​ # 查询员工的工资级别

​ select grade_level ,last_name,salary from employees e inner join job_grades g on e.salary between g.lowest_sal and g.highest_sal order by salary desc;

​ # 查询每个工资级别的降序排序;

​ select 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(*) > 2 order by grade_level desc;

自连接:

​ # 查询员工名字和上级名字

​ select e1.last_name,e1.employee_id,e1.manager_id,e2.last_name,e2.employee_id from employees e1 inner join employees e2 on e1.manager_id = e2.employee_id;

​ # 查询名字包含K的员工名字和上级名字

​ select e1.last_name,e1.employee_id,e1.manager_id,e2.last_name,e2.employee_id from employees e1 inner join employees e2 on e1.manager_id = e2.employee_id where e1.last_name like “%k%”;

外连接

场景:

​ 用于查询一个表中有,另一个表中没有的记录。

​ 把女表当成主表,而boy表则为从表,主表的数据全部显示,匹配上的从表才会显示。

​ 分为两部分,一部分为交集本分,另一部分为主表有,但是从表匹配不上的部分。用null填充。

​ 外连接结果 = 内连接结果 + 主表有但从表没有的记录。

​ 如果left join,左连接,则左边主表,right join 有连接,则右边主表。

​ 左外和右外交换两个表的顺序,则可以实现相同效果。

​ 要查询的信息主要来自于哪个表,谁就是主表。

​ 全外结果为 = 交集部分+左边没匹配上为空+右边没匹配上为空

left [outer]

​ case1;查询没有男朋友的女神名

​ select name,boyName from beauty b left join boys y on b.boyfriend_id = y.id where y.id is null;

​ 把女表当成主表,而boy表则为从表,主表的数据全部显示,匹配上的从表才会显示。最好选择id来判断,因为id作为主键不可能为null,只可能是没匹配上。

​ case2:若俩表顺序交换,数据为?

​ 显示所有男生及他们的女朋友,若无为空。

​ case3:查询哪个部门没有员工?

​ select e.employee_id,d.department_id,department_name from departments d left join employees e on e.department_id = d.department_id where e.employee_id is null;

right [outer]

​ case1;查询没有男朋友的女神名

​ select name,boyName from boys y right join beauty b on b.boyfriend_id = y.id where y.id is null;

full [outer]

​ 全外结果为 = 交集部分+左边没匹配上为空+右边没匹配上为空

​ select b.*,bo.* from beauty b full outer join boys bo on b.boyfriend_id = bo.id;

​ mysql不支持全外连接

交叉连接

cross join

​ 结果为量表的笛卡尔乘积

​ case1:使用99语法来实现的笛卡尔乘积

​ select b.*,bo.* from beauty b cross join boys bo;

​ 没有顺序关系

SQL92HE SQL99的PK

功能:

​ sql99支持的较多

可读性:

​ sql99实现连接条件和筛选条件的分离,可读性较高

常见的几种连接:

​ 取交集:内连接 inner join

​ 表A所有记录:A左外B,B右外A

​ 表B所有记录:A右外B,B左外A

​ 表A所有记录-交集: A左外B,B右外A 再加条件。

​ 表B所有记录-交集:A右外B,B左外A 再加条件。

​ 全部:全外full join

​ 全部-交集:全外full join 再加条件。

作业:

​ case1:查询编号>3的女神的男朋友编号,如果有则列出详情,如果没,则用null。

​ select b.*,be.id,be.name from beauty be left join boys b on be.boyfriend_id = b.id where be.id > 3 order by be.id ;

​ case2:查询哪个城市没有部门。

​ select city,department_name from locations l left join departments d on l.location_id = d.location_id where d.department_id is null;

​ case3:查询部门为SAL或IT的员工信息。

​ select e.*,department_name from employees e left join departments d on d.department_id = e.department_id where d.department_name in(“SAL”,“IT”) order by e.employee_id;

子查询

含义:

​ 出现在其他语句(增删改也可以,但查询最多)重点select语句,称为子查询或内查询。

​ 外部的查询,称为主查询或外查询

示例:

​ select first_name from employees where department_id in (select department_id from departments where location_id = 1700)

分类:

​ 子查询出现位置:

​ select 后

​ 仅仅支持标量子查询

​ from 后

​ 支持表子查询

​ where或having后 重点

​ 支持标量子查询重点

​ 支持列子查询重点

​ 也支持行子查询,但是用的较少

​ exists 后 (相关子查询)

​ 表子查询

​ 结果集的行列数不同

​ 标量子查询(结果集只有一行一列) 主要!

​ 列子查询(结果集只有一列多行)

​ 行子查询(结果集可以有多行多列)

​ 表子查询(结果集一般为多行多列)

where或having后边

​ 特点:

​ 子查询都会放在小括号内

​ 子查询一般放在条件的右侧

​ 标量子查询,一般搭配着单行操作符使用

​ < >= …

​ 列子查询 一般搭配值多行操作符使用

​ in any/some all

​ 子查询的执行时优先于主查询执行,主查询条件用到了子查询的结果

​ 非法使用标量子查询的情况:

​ 如:查询最低工资大于50号部门最低工资的部门id和其最低工资

​ select department_id,min(salary) from employees group by department_id having min(salary) > (select salary from employees where department_id = 50);

​ 该用标量子查询时,使用了列子查询,报错。>只能搭配标量子查询

​ select department_id,min(salary) from employees group by department_id having min(salary) > (select salary from employees where department_id = 250);

​ 该子查询的结果也不是一行一列,也构成非法使用。

标量子查询(单行子查询)

​ 一般搭配着单行操作符使用

​ case 1 :谁的工资比abel高

​ select salary,last_name from employees where salary > (select salary from employees where last_name = “Abel”);

​ case2:返回job_id与141好员工相同,salary比143好员工多的员工,姓名,job_id,工资

​ select * from employees where job_id = (select job_id from employees where employee_id = 141) and salary > (select salary from employees where employee_id = 143);

​ case3:返回公司工资最少的员工的信息

​ select * from employees where salary = (select min(distinct salary) from employees);

​ case4:查询最低工资大于50号部门最低工资的部门id和其最低工资

​ select department_id,min(salary) from employees group by department_id having min(salary) > (select min(salary) from employees where department_id = 50);

列子查询(多行子查询)

​ 一般搭配多行比较操作符使用, in,any|some,all

​ in 等于列表中的任意一个

​ any|some 和子查询返回的某一个值比较,有歧义,且可以被代替,所以使用率不高

​ all 和子查询返回的所有值比较,也可以被替代。

​ case1:返回location_id是1400或1700的部门中的员工姓名

​ select last_name from employees where department_id in (select department_id from departments where location_id in (1400,1700));

​ in 也可以换为 = any

​ case2:返回其他部门中比job_id为“IT_PROG”部门任意工资低的员工的员工号,姓名,job_id以及salary

​ select last_name,job_id,salary from employees where salary < any(select salary from employees where job_id = “IT_PROG”) and department_id not in (select department_id from employees where job_id = “IT_PROG”);

​ case3:返回其他部门中比job_id为“IT_PROG”部门所有工资低的员工的员工号,姓名,job_id以及salary

​ select last_name,job_id,salary from employees where salary < all(select salary from employees where job_id = “IT_PROG”) and department_id not in (select department_id from employees where job_id = “IT_PROG”);

行子查询(结果集一行多列或多行多列)

​ case1:查询员工编号最小并且工资最高的员工信息

​ 这样的员工不一样存在

​ 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);

select 后面

​ 仅仅支持标量子查询

​ case1:查询每个部门的员工个数

​ select *,(select count(*) from employees e where e.department_id = d.department_id) from departments d;

​ case2:查询员工号为102的部门名

​ select employee_id,(select department_name from departments d where d.department_id = e.department_id ) from employees e where employee_id = 102;

from后面

​ 将子查询结果充电一张表,要求必须起别名

​ case1:查询每个部门的平均工资的工资等级

​ select grade_level,a.department_id,ab from (select avg(salary) ab,department_id from employees group by department_id) a left join job_grades on ab between lowest_sal and highest_sal;

​ 这里的avg(salary)要起别名,因为外部要用到这个字段,若直接拼写这个字段,会被认为分组函数。

exists后面(相关子查询)

​ 语法:

​ exists(完整的查询语句)

​ 结果 1 和 0

​ 可以被代替,所以使用的比较少

​ 子查询涉及到了主查询的字段,

​ case1:查询有部门员工的部门名

​ select department_name from departments d where exists(select * from employees e where d.department_id = e.department_id);

​ #in方法,能用exists方法决定能用in

​ select department_name from departments d where department_id in (select distinct department_id from employees );

​ case2:查询没有女朋友的男人

​ select boyName from boys b where not exists (select * from beauty t where t.boyfriend_id = b.id);

作业

​ case1:查询和zlotkey相同部门的员工姓名和工资

​ select last_name,salary from employees e where last_name != “zlotkey” and e.department_id = (select department_id from employees where last_name = “zlotkey”);

​ case2:查询工资比公司平均工资高的员工的员工号,姓名和工资

​ select employee_id,last_name,salary from employees e where salary > (select avg(salary) from employees) order by salary;

​ case3:查询个部门中工资比本部门平均工资高的员工的员工号和姓名

​ select employee_id,last_name from employees e where salary > (select avg(salary) from employees a where a.department_id = e.department_id);

​ case4:查询和姓名中包含字母u的员工在相同部门的员工号和姓名

​ select employee_id,last_name from employees e where e.department_id in (select department_id from employees a where last_name like “%u%”);

​ case5:查询在部门location_id是1700的部门工作的员工的员工号

​ select employee_id from employees e where e.department_id in (select department_id from departments where location_id = 1700);

​ case6:查询管理者是king的员工姓名和工资

​ select last_name,salary from employees e where manager_id in (select employee_id from employees a where last_name = “k_ing” );

​ case7:查询工资最高的员工的姓名,要求f_name和l_name显示为一列

​ select concat(first_name,last_name) as name from employees where salary = (select MAX(salary) from employees);

分页查询

当要显示的数据,一页显示不全,需要分页提交sql请求

语法:

​ select 查询列表 from 表 【join type join 表2 on 连接条件 where…order by】 limit 1,1;

​ from – join —on—where --group by --having—select --order by ----limit

特点:

​ limit语句放在查询语句的最后

​ 公式要显示页数是page,没页条目数size

​ …limit (page-1)*size,size;

limit:

​ limit 其实索引,条目数;(起始索引从0开始,其他的是1)

​ case1:查询前五条元工信息

​ select * from employees limit 5;

​ case2:查询低11条到25条

​ select * from employees limit 10,15;

​ case3: 查询有奖金的员工工资前十名

​ select salary,last_name,commission_pct from employees where commission_pct is not null order by salary desc limit 10;

子查询经典案例

​ case1:查询工资最低的员工信息

​ select * from employees where salary <= all (select salary from employees );

​ case2:查询平均工资最低的部门信息和该部门的平均工资

​ select department_id,department_name,(select avg(salary) from employees e where e.department_id = d.department_id ) as avg_salary from departments d where department_id = (select department_id from employees group by department_id order by avg(salary) limit 1);

​ case3:查询平均工资最低的部门信息和该部门的平均工资

​ select d.*,(select avg(salary) from employees e1 where e1.department_id = d.department_id) as avg_salary from departments d where d.department_id = (select department_id from employees e group by department_id order by avg(salary) limit 1);

​ case4:查询平均工资最高的job信息

​ select * from jobs where job_id = (select job_id from employees group by job_id order by avg(salary) desc limit 1);

​ case5:查询平均工资高于公司平均工资的部门有哪些

​ select department_id from employees group by department_id having avg(salary) > (select avg(salary) from employees);

​ case6:查询出公司所有manager的详细信息

​ select * from employees e where e.employee_id in (select distinct manager_id from employees );

​ case7:各个部门中最高工资中最低的那个部门的的最低工资是多少

​ select salary from employees e where e.department_id = (select department_id from employees group by department_id order by max(salary) limit 1) order by salary limit 1;

​ case8:查询平均工资最高的部门的manager的详细信息;

​ select * from employees e where e.employee_id = (select manager_id from departments d where d.department_id = (select department_id from employees group by department_id order by avg(salary) desc limit 1));

联合查询

union:

​ 联合,合并:将多条查询语句的结果合并为一个结果

​ case1:部门编号大于90或邮箱中包含a的员工信息

​ select * from employees where department_id > 90 or email like “%a%”;

​ 若使用联合查询

​ select * from employees where email like “%a%”

​ union

​ select * from employees where department_id >90;

语法:

​ 查询语句1

​ union

​ 查询语句2

​ union

​ …

场景:

​ 当查询结果来自于多个表时,且多个表每一直接的连接关系,但查询的信息是一致时。

​ 例如:查询中国用户为男的信息以及外国用户为男性的用户信息

特点:

​ 要求多条查询语句的查询列数是一致的。

​ 要求多条查询语句的灭一列的类型和顺序最好是一致的。

​ 若字段名字不一样,则显示字段名为第一张表的字段名字。

​ 联合查询会去重重复项,若想不去除,此时union替换为union all

おすすめ

転載: blog.csdn.net/MINGZHEFENG/article/details/106903648