# 准备数据
~~~
-- 新建 user1 表
create table if not exists user1 (
id smallint unsigned primary key auto_increment,
user_name varchar(40),
over varchar(40)
);
-- 新建 user2 表
create table if not exists user2 (
id smallint unsigned primary key auto_increment,
user_name varchar(40),
over varchar(40)
);
-- 新建 user_kills 表
create table if not exists user_kills (
id smallint unsigned primary key auto_increment,
user_id smallint unsigned,
timestr timestamp default CURRENT_TIMESTAMP,
kills smallint unsigned
);
insert into user1 (user_name,over) values ('唐僧','功德佛'),('猪八戒','净坛使者'),('孙悟空','斗战胜佛'),('沙僧','金身罗汉');
insert into user2 (user_name) values ('孙悟空','成佛'),('牛魔王','被降服'),('蛟魔王','被降服'),('鹏魔王','被降服'),('狮驼王','被降服');
insert into user_kills (user_id,timestr,kills) values ('2','2017-01-10 00:00:00','10'),('2','2017-02-01 00:00:00','2'),('2','2017-02-05 00:00:00','12'),('4','2017-01-10 00:00:00','3'),('2','2017-02-11 00:00:00','5'),('2','2017-02-06 00:00:00','1'),('3','2017-01-11 00:00:00','20'),('2','2017-02-12 00:00:00','10'),('2','2017-02-07 00:00:00','17');
~~~
# 全连接
MySQL不支持FULL JOIN
解决方法:
通过UNION将左连接和右连接的结果合并
~~~
SELECT select_expressions
FROM TABLE A LEFT OUTER JOIN TABLE B ON A.key=B.key
UNION ALL
SELECT select_expressions
FROM TABLE A RIGHT OUTER JOIN TABLE B ON A.key=B.key;
~~~
**UNION会自动删除重复项,刷选出部分字段的时候要注意了,如果刷选出来的两个字段的值完全相同就会剩下一个。**
**UNION ALL 和 UNION 不同之处在于 UNION ALL 会将左右两个查询的结果的所有的资料都列出来,无论资料值有无重复。**
![](https://box.kancloud.cn/f6242a30749221bfa19744d408ddf5be_1052x415.jpg)
# 内连接
join的内连接是抽取两张表的公共部分
内连接(inner join) 可以选取A表和B表的交集 select 字段 from A表 a表别名 inner join B表 b表别名 on a.字段=b.字段;
# 左外连接
not in 关键字不会使用索引 所以用left join加上关键字为null查找只存在于A表不存在于B表的数据
![](https://box.kancloud.cn/89a8883db477157333bea616c09468b3_792x442.jpg)
LEFT OUTER JOIN:包含左表中的所有数据,当某个连接谓词不在右表中时,新生成的表的右表字段为NULL。对左表数据的信息进行扩展,增加右表中的字段,当某个连接谓词不在右表中时,新生成的表的右表字段为NULL。
使用LEFT OUTER JOIN对NOT IN 进行优化。
# 右外连接
RIGHT OUTER JOIN:包含右表中的所有数据,当某个连接谓词不在左表中时,新生成的表的左表字段为NULL。对右表数据的信息进行扩展,增加左表中的字段,当某个连接谓词不在左表中时,新生成的表的左表字段为NULL。
使用RIGHT OUTER JOIN对NOT IN 进行优化。
~~~
SELECT select_sxpressions
FROM TABLE A RIGHT OUTER JOIN TABLE B ON A.key=B.key
WHERE A.key IS NULL;
~~~
表B中不包含表A中的数据。
~~~
SELECT select_sxpressions
FROM TABLE A RIGHT OUTER JOIN TABLE B ON A.key=B.key
WHERE A.key IS NOT NULL;
~~~
表A与表B的交集,相当于INNER JOIN。
![](https://box.kancloud.cn/63a500dce294b56e328a3d29a79c9efb_823x467.jpg)
# 交叉连接
CROSS JOIN:笛卡尔连接,如果A和B是两个集合,它们的交叉连接就记为A X B。一个表的每个记录与另一个表的所有记录进行连接,形成`A.length*B.length`个数据项的表。(无需提供ON)
~~~
SELECT select_expressions
FROM TABLE A CROSS JOIN TABLE B;
~~~
在实际的使用中,要尽量避免产生笛卡尔积的查询,因为很少情况我们会使用到笛卡尔积的查询结果,但是在一些特殊情况下,我们需要笛卡儿积查询产生我们需要的结果。
# join更新表
![](https://box.kancloud.cn/dc43e1d8e19c07ead5a6841d113faa71_710x349.jpg)
先select出同一表中的某些值,再update这个表(在同一语句中)
mysql不支持这种,不能更新出现在from从句中,where后面你用了更新表user1作为子查询表这是不容许的,其他的一些sql支持
~~~
update user1 a join
(select b.'user_name' from user1 a join user2 b on a.'user_name'=b.'user_name')
b on a.'user_name' = b.'user_name' set a.over='齐天大圣';
~~~
也就是说将select出的结果再通过中间表select一遍,这样就规避了错误。注意,这个问题只出现于mysql,mssql和oracle不会出现此问题。
# 子查询
## join优化子查询技巧:
![](https://box.kancloud.cn/0d49d9d7571dc89d3cbda554a3b183d7_837x313.jpg)
一般子查询写法:(数据小时,没有多大影响,如果数据量大时,则要消耗大量的查询)
~~~
select a.user_name , a.over , (select over from user2 b where a.user_name = b.user_name) as over2
from user1 a;
~~~
如果这两张表的记录相当多 那么这个子查询相当于对A标的每一条记录都要进行一次子查询。
join优化(左连接)后的写法:
~~~
select a.user_name , a.over , b.over from user1 a
left join user2 b on a.user_name = b.user_name
~~~
## join优化聚合子查询
~~~
-- 如何查询打怪最多的日期
select a.user_name,b.timestr,b.kills from
user1 a join user_kills b on a.id=b.user_id
where
b.kills=(select max(c.kills) from user_kills c where c.user_id=b.user_id);
-- 优化后语句 避免子查询
select a.user_name,b.timestr,b.kills from user1 a inner join user_kills b on a.id=b.user_id inner join user_kills c on c.user_id=b.user_id group by a.user_name,b.timestr,b.kills having b.kills = max(c.kills);
~~~
## 分组选择数据
分组选择解决的问题?
如果说在几组数据中寻找最大或者最小的记录那么很好找,可以用聚合函数达到目的 ,但是如果要在分类中选择几条记录那么就需要分组选择了
比如在取经四人组中查出每人前2天的杀怪记录
![](https://box.kancloud.cn/f0437102bf1e3c68ee388791d74cd785_952x370.jpg)
采用ROW_NUMBER函数,进行分区排序
使用WITH 表名 AS (),不过MySQL中不支持ROW_NUMBER() OVER(PARTITION BY 字段名 )
row_number() OVER(PARTITION BY)与 rank() OVER(PARTITION BY) 区别:前者有两个并列第一则返回一条记录,后者返回两条,同时是跳跃排序;dense_rank()是连续排序!!(mySql中不支持这种查询方法)
可以通过这个方法来实现
![](https://box.kancloud.cn/b29d7d663d58dddcb0249bb543e8db69_858x416.jpg)
还有个
![](https://box.kancloud.cn/63c2fcc3d162f481edaaec7795062fef_2421x1125.jpg)
- SQL
- 名词
- mysql
- 初识mysql
- 备份和恢复
- 存储引擎
- 数据表损坏和修复
- mysql工具
- 数据库操作
- 增
- 删
- 改
- 查
- 数据类型
- 整数类型
- 小数类型
- 日期时间类型
- 字符和文本型
- enum类型
- set类型
- 时间类型
- null与not null和null与空值''的区别
- 数据表操作
- 创建
- 索引
- 约束
- 表选项列表
- 表的其他语句
- 视图
- sql增删改查
- sql增
- sql删
- sql改
- sql查
- sql语句练习
- 连接查询和更新
- 常用sql语句集锦
- 函数
- 字符函数
- 数值运算符
- 比较运算符与函数
- 日期时间函数
- 信息函数
- 聚合函数
- 加密函数
- null函数
- 用户权限管理
- 用户管理
- 权限管理
- pdo
- 与pdo相关的几个类
- 连接数据库
- 使用
- pdo的错误处理
- pdo结果集对象
- pdo结果集对象常用方法
- pdo预处理
- 常用属性
- mysql编程
- 事务
- 语句块
- mysql中的变量
- 存储函数
- 存储过程
- 触发器
- mysql优化
- 存储引擎
- 字段类型
- 三范式和逆范式
- 索引
- 查询缓存
- limit分页优化
- 分区
- 介绍
- 分区算法
- list分区
- range范围
- Hash哈希
- key键值
- 分区管理
- 特别注意
- 分表
- 数据碎片与维护
- innodb表压缩
- 慢查询
- explain执行计划
- count和max,groupby优化
- 子查询优化
- mysql锁机制
- 介绍
- 演示
- 总结
- 乐观锁和悲观锁
- 扛得住的mysql
- 实例和故事
- 系统参数优化
- mysql体系结构
- mysql基准测试
- 索引
- mysql的复制
- win配置MySQL主从
- mysql5.7新特性
- 常见问题
- general log
- 忘记密码
- uodo log与redo log
- 事务隔离级别
- mysql8密码登录
- explain
- 高效的Tree表
- on delete cascade 总结
- mongod
- 简介
- 集合文档操作语句
- 增删改查
- 索引
- 数据导入和导出
- 主从复制
- php7操作mongod
- 权限管理
- redis
- redis简介
- 3.2版本配置文件
- 3.0版本配置文件
- 2.8版本配置文件
- 配置文件总结
- 外网连接
- 持久化
- RDB备份方式保存数据
- AOF备份方式保存数据
- 总结
- win安装redis和sentinel部署
- 事务
- Sentinel模式配置
- 分布式锁
- 管道
- php中redis代码
- 发布订阅
- slowlog
- Redis4.0
- scan和keys
- elasticsearch
- 配置说明
- 启动
- kibana
- kibana下载
- kibana配置文件
- kibana常用功能
- 常用术语
- Beats
- Beats简介
- Filebeat
- Packetbeat
- Logstash
- 配置
- elasticsearch架构
- es1.7
- head和bigdesk插件
- 插件大全
- 倒排索引
- 单模式下API增删改查
- mget获取多个文档
- 批量操作bulk
- 版本控制
- Mapping映射
- 基本查询
- Filter过滤
- 组合查询
- es配置文件
- es集群优化和管理
- logstash
- kibana
- es5.2
- 安装
- 冲突处理
- 数据备份
- 缺陷不足
- 集群管理api
- 分布式事务
- CAP理论
- BASE模型
- 两阶段提交(2PC)
- TCC (Try-Confirm-Cancle)
- 异步确保型
- 最大努力通知型
- 总结