环境
mysql:mysql-5.7.17-winx64
navicat for mysql:11.1.13
前言
本人玩nosql
,玩了三年,结果呢,SQL
忘的差不多了,所以今天特意把一些基本概念和用法捡回来;
这三年来,玩nosql
(主要针对mongodb
和es
库),可以说玩的贼溜;
还好自己是科班出身,大学本来就学过,把SQL
捡回来也是很快,哈哈;
话不多说,先上图:
表
为了方便讲解,我们先假设有如下表
学生表(students
)
这里我们再复制一张学生表(students_copy
)
成绩表(scores
)
id:主键;自增
sid:就是学生id
cid:就是教师id
score:分数
教师表(teachers
)
连接查询
根据表的不同,如果是自己和自己进行关联查询,称为自连接
;
如果是不同表之间进行关联查询,就分为内连接
、外连接
和交叉连接
自连接
即:表自己和自己关联
-- 自连接
SELECT * FROM students s,students s2 WHERE s.id = s2.id;
效果:
内连接
内连接其实就是取交集;所以数据会有丢失;
自然连接
语法:
select ... from A natural join B [where]
百度百科的说法:
自然连接(Natural join)是一种特殊的等值连接,它要求两个关系中进行比较的分量必须是相同的属性组,并且在结果中把重复的属性列去掉。而等值连接并不去掉重复的属性列。
但是具体该怎么理解呢?直接看图(用美图秀秀的拼图功能):
上图 左边是students
表,右边是students_copy
表;
执行:
-- 自然连接
SELECT * FROM students s NATURAL JOIN students_copy ssc
效果:
上面是两个表字段都一模一样的效果图;
要是表字段不一样呢(大部分)?比如和教师表关联
-- 自然连接
SELECT * FROM students s NATURAL JOIN teachers t
总结:
①自然连接,应该是依次比较字段名相同的值是否也相同;如果至少有一个相同,则关联成功,并把关联表中多余的字段也添加进结果;
拿上例来说,tname
字段,在students
表中没有的,来自关联表(teachers
),最后也添加进了结果集中。
② 可以使用where
进行筛选;
等值连接
在连接条件中使用等于号(=)运算符比较被连接列的列值,其查询结果中列出被连接表中的所有列,包括其中的重复列
语法:
SELECT ... FROM A INNER JOIN B [WHERE/ON s.id = sc.sid];
执行:
-- 等值连接
SELECT * FROM students s INNER JOIN scores sc WHERE s.id = sc.sid;
-- 等效于
SELECT * FROM students s , scores sc WHERE s.id = sc.sid;
SELECT * FROM students s , scores sc ON s.id = sc.sid;
不等值连接
定义:
在连接条件使用除等于运算符以外的其它比较运算符比较被连接的列的列值。这些运算符包括>、>=、<=、<、!>、!<和<>。
执行:
-- 不等连接
SELECT * from students s INNER JOIN scores sc WHERE s.id <> sc.sid
-- 等效于
SELECT * from students s, scores sc WHERE s.id <> sc.sid;
-- 不能讲where换成on,会报错
SELECT * from students s, scores sc on s.id <> sc.sid;
-- 但是在指明为内连接的情况下,可以
SELECT * from students s INNER JOIN scores sc on s.id <> sc.sid;
结果:
外连接
(假设有集合A、B两个集合
)
与内连接不同的是,外连接的基础表数据是完整的。
用集合来说的话,就是集合的范围为 A与B交集
+ A
(假设A
为基础表)
左外连接
即:以左边的表为基础表,进行关联,没关联上的字段,显示为null
语法格式:
select ... from A left join B on A.id = B.id
注意:
上面的
on
是不能省略的
执行:
-- 左外连接
select ... from students s LEFT JOIN students_copy ssc on s.id = ssc.id;
总结:
从上图可以看出,基础表的6条数据都显示出来了,关联表里关联上的就显示为null;
右外连接
即:以右边的表为基础表,字段都保留,没关联上的字段就显示null
。
语法格式:
select ... from A right join B on A.id = B.id
注意:
上面的
on
是不能省略的
说明:
右外连接其实和左外连接是一回事,在左外连接的写法上,把A、B两个表交换位置,就变成了右外连接
执行:
-- 右外连接
SELECT * FROM students s RIGHT JOIN students_copy ssc on s.id = ssc.id;
效果:
总结:
基础表(右边的数据)是完整的,左边没有关联上的,就显示为null;
全连接
没关联的数据字段就显示为null
,基本表和关联表的数据都保留。
语法:
select ... from A FULL JOIN B on A.id = B.id;
注意:
上面的
on
是不能省略的;
说明: 目前mysql
是不支持全连接的,Oracle
数据库i9
以上是支持的。
执行:
-- 全连接
SELECT * FROM students s FULL JOIN students_copy ssc on s.id = ssc.id;
效果,报错:
[SQL]-- 全连接
SELECT * FROM students s FULL JOIN students_copy ssc on s.id = ssc.id;
[Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FULL JOIN students_copy ssc on s.id = ssc.id' at line 2
交叉连接
就是做笛卡尔积
语法:
select ... from A cross join B
-- 交叉连接
SELECT * FROM students s CROSS join students_copy ssc;
-- 等效于
SELECT * FROM students s, students_copy ssc;
-- 结果是一样的
SELECT * FROM students s INNER join students_copy ssc;
效果:
注意:
这里你会发现,交叉连接查询的结果和INNER JOIN 没有指定on或者where时,结果是一样的,都是笛卡尔积。
可以使用where或者on进行筛选查询。
ON 注意事项
① 不能在自然连接(natural join
)中使用。
②不等值连接中,不能写成如下形式:
SELECT * from students s, scores sc on s.id <> sc.sid;
但是可以写成如下形式:
SELECT * from students s INNER JOIN scores sc on s.id <> sc.sid;
为什么会有这种区别呢?
这是因为关键字ON
和select
、from
、where
其实不是一个级别的;
select
、from
、where
这些关键字属于顶级关键字,是可以单独使用的;
但是关键字ON
,必须和inner join
、left join
、cross join
配合来用的。
所以出现如下形式,也是错误的:
SELECT * FROM scores sc, students s on s.id = sc.sid;
会报如下错误:
[SQL]SELECT * FROM scores sc, students s on s.id = sc.sid;
[Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'on s.id = sc.sid' at line 1
join和union区别
- join联结的两个表,是通过匹配两个表中相同字段的相同的值,得到的结果集。可以认为是结果集的列拓宽了。join是使得查询的内容更详细了。
- union是取将两个结果集的并集,但两个结果集所拥有的列数是一样、列的顺序也一样、字段类型相同或相似(DBMS认为的相似),才能union并展示在一起。可以认为是结果集的行数多了。union是使得查询的结果更多了。
union会对查到的结果进行去重处理。
union all会将查到的结果直接全部展示出来。
总结
基本把SQL
语法捡回来了,并且把关键字ON
,算是弄明白了。
参考地址:
https://www.cnblogs.com/caozengling/p/5318696.html
http://www.cnblogs.com/zxlovenet/p/4005256.html
https://blog.csdn.net/jiuqiyuliang/article/details/10474221
https://zhuanlan.zhihu.com/p/46037197
https://blog.csdn.net/u010895119/article/details/80335983
https://blog.51cto.com/12902932/1928058