【数据库9】表连接
2015-11-16 23:30
288 查看
原文链接:http://blog.csdn.net/coder_pig/article/details/43869305
本节引言:
前面我们学习的都是针对一个表来进行操作的,上一节虽然学了UNION这个可以操作多个表
的关键字,但是又有两个限制(查询字段数目与数据类型要相同),本节就来学习通过表连接
来操作多个表!而表连接又有四种:
内连接,外连接,交叉连接与自连接,那么接下来开始本节学习!
数据准备:
在开始学习前,我们先准备一些数据,建三个表:T_Stu,T_Class,T_Dorm
建T_Stu表:
[sql] view
plaincopyprint?
CREATE TABLE T_Stu
(
SId INTEGER,
SName VARCHAR(20),
Cl_id INTEGER,
Do_id INTEGER,
)
建T_Class表
[sql] view
plaincopyprint?
CREATE TABLE T_Class
(
Cl_id INTEGER,
Cl_name VARCHAR(10)
)
建立T_Drom表:
[sql] view
plaincopyprint?
CREATE TABLE T_Drom
(
Do_id INTEGER,
Do_name VARCHAR(10)
)
好了,表就建立好了,这里是为了演示多表连接,并没有为表设置主键,大家
平时要养成为每个表设置主键的习惯,好了,接下来就录入一些数据吧!
先插入T_Stu:
[sql] view
plaincopyprint?
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(1,'洪磊',1,1);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(2,'兴堂',3,1);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(3,'兴湘',2,2);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(4,'孑帆',2,1);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(5,'兴华',1,1);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(6,'维瑞',1,2);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(7,'俐杰',2,2);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(8,'刘洋',3,2);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(9,'安泰',1,1);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(10,'月岑',1,1);
接着到T_Class表:
[sql] view
plaincopyprint?
INSERT INTO T_Class(Cl_id,Cl_name)VALUES(1,'初一(2)班');
INSERT INTO T_Class(Cl_id,Cl_name)VALUES(2,'初二(1)班');
INSERT INTO T_Class(Cl_id,Cl_name)VALUES(3,'初三(4)班');
最后到T_Drom表:
[sql] view
plaincopyprint?
INSERT INTO T_Drom(Do_id,Do_name)VALUES(1,'4栋');
INSERT INTO T_Drom(Do_id,Do_name)VALUES(2,'6栋');
被连接表中的所有列,包括重复列,这也是和②自然连接的不同!
例子:
[sql] view
plaincopyprint?
SELECT * FROM T_Stu INNER JOIN T_Class
ON T_Stu.Cl_id = T_Class.Cl_id
运行SQL:
例子:
[sql] view
plaincopyprint?
SELECT SId AS '学生编号',SName AS '学生姓名',Cl_name AS '所在班级' FROM T_Stu INNER JOIN T_Class
ON T_Stu.Cl_id = T_Class.Cl_id
运行SQL:
就是修改下=号而已,这里不讲解!
接着演示下连接多个表的写法:
[sql] view
plaincopyprint?
SELECT SId AS '学生编号',SName AS '学生姓名',
Cl_name AS '所在班级',Do_name AS '所在宿舍' FROM T_Stu
INNER JOIN T_Class ON T_Stu.Cl_id = T_Class.Cl_id
INNER JOIN T_Drom ON T_Stu.Do_id = T_Drom.Do_id
运行SQL:
上面就把三个表连接起来了,每增加一个表,只需:
添加INNER JOIN 表名 ON(匹配条件)即可!
表名太长,写起来麻烦,那么就使用别名:
[sql] view
plaincopyprint?
SELECT s.SId AS '学生编号',s.SName AS '学生姓名',
c.Cl_name AS '所在班级',d.Do_name AS '所在宿舍' FROM T_Stu s INNER JOIN T_Class c
ON s.Cl_id = c.Cl_id INNER JOIN T_Drom d
ON s.Do_id = d.Do_id
运行的效果也是一样的!
外连接不需要两个表都具有匹配记录,这样可以指定某个表中的记录总是放到结果集中!
简单点就是说:返回到结果集中的不仅包含符合条件的行,还包括左表(左外连接)、右表
(右外连接)或者两个连接表(完全连接)中的所有数据行!
[sql] view
plaincopyprint?
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(11,'小明',null,null);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(12,'小红',null,null);
接下来我们使用左外连接:
[sql] view
plaincopyprint?
SELECT s.SId AS '学生编号',s.SName AS '学生姓名',
c.Cl_id AS '班级编号',c.Cl_Name '所在班级'
FROM T_Stu AS s LEFT OUTER JOIN T_Class AS c ON
s.Cl_id = c.Cl_id
运行SQL:
先往T_Class表中插入两条记录:
[sql] view
plaincopyprint?
INSERT INTO T_Class(Cl_id,Cl_name)VALUES(4,'高一(2)班');
INSERT INTO T_Class(Cl_id,Cl_name)VALUES(5,'高三(1)班');
接下来把左外连接中的LEFT OUTER JOIN改成RIGHT OUT JOIN即可!
[sql] view
plaincopyprint?
SELECT s.SId AS '学生编号',s.SName AS '学生姓名',
c.Cl_id AS '班级编号',c.Cl_Name '所在班级'
FROM T_Stu AS s RIGHT OUTER JOIN T_Class AS c ON
s.Cl_id = c.Cl_id
运行SQL:
把上面的RIGHT OUTER JOIN该成:FULL OUTER JOIN即可!
[sql] view
plaincopyprint?
SELECT s.SId AS '学生编号',s.SName AS '学生姓名',
c.Cl_id AS '班级编号',c.Cl_Name '所在班级'
FROM T_Stu AS s FULL OUTER JOIN T_Class AS c ON
s.Cl_id = c.Cl_id
运行SQL:
第一个表的行数乘以第二个表的行数等于笛卡尔积结果集的大小。
又分为两种,隐式与显式!
隐式的超简单,直接select ... From后直接加上交叉连接的表名列即可!
比如:
[sql] view
plaincopyprint?
SELECT * FROM T_Stu,T_Class
显式的:
[sql] view
plaincopyprint?
SELECT * FROM T_Stu cross join T_Class
大部分的DBMS都支持CROSS JOIN显式的交叉连接,而隐式的所有DBMS都支持!
即连接关键字的两边都是同一个表!
一个形象的例子就是地区表!
创建一个简单的地区表,接着录几条数据!
建表SQL:
[sql] view
plaincopyprint?
CREATE TABLE T_City
(
CId INTEGER,
CName VARCHAR(10),
CBelong VARCHAR(10),
PRIMARY KEY (CId)
)
插入几条数据:
[sql] view
plaincopyprint?
INSERT INTO T_City(CId,CName,BId)VALUES(1,'北京',NULL);
INSERT INTO T_City(CId,CName,BId)VALUES(2,'上海',NULL);
INSERT INTO T_City(CId,CName,BId)VALUES(3,'天津',NULL);
INSERT INTO T_City(CId,CName,BId)VALUES(4,'重庆',NULL);
INSERT INTO T_City(CId,CName,BId)VALUES(5,'南京',6);
INSERT INTO T_City(CId,CName,BId)VALUES(6,'江苏',NULL);
INSERT INTO T_City(CId,CName,BId)VALUES(7,'苏州',6);
INSERT INTO T_City(CId,CName,BId)VALUES(8,'无锡',6);
INSERT INTO T_City(CId,CName,BId)VALUES(9,'广东',NULL);
INSERT INTO T_City(CId,CName,BId)VALUES(10,'揭阳',9);
接下来就到自连接了:
[sql] view
plaincopyprint?
SELECT a.CName,b.CName
FROM T_City as a INNER JOIN T_City as b
ON a.CId = b.Bid
运行自连接的SQL:
你也可以统计辖区数:
[sql] view
plaincopyprint?
SELECT a.CName,COUNT(b.CId) as '辖区数'
FROM T_City as a INNER JOIN T_City as b
ON a.CId = b.Bid
GROUP BY a.CName
运行上述SQL:
本节引言:
前面我们学习的都是针对一个表来进行操作的,上一节虽然学了UNION这个可以操作多个表
的关键字,但是又有两个限制(查询字段数目与数据类型要相同),本节就来学习通过表连接
来操作多个表!而表连接又有四种:
内连接,外连接,交叉连接与自连接,那么接下来开始本节学习!
数据准备:
在开始学习前,我们先准备一些数据,建三个表:T_Stu,T_Class,T_Dorm
建T_Stu表:
[sql] view
plaincopyprint?
CREATE TABLE T_Stu
(
SId INTEGER,
SName VARCHAR(20),
Cl_id INTEGER,
Do_id INTEGER,
)
建T_Class表
[sql] view
plaincopyprint?
CREATE TABLE T_Class
(
Cl_id INTEGER,
Cl_name VARCHAR(10)
)
建立T_Drom表:
[sql] view
plaincopyprint?
CREATE TABLE T_Drom
(
Do_id INTEGER,
Do_name VARCHAR(10)
)
好了,表就建立好了,这里是为了演示多表连接,并没有为表设置主键,大家
平时要养成为每个表设置主键的习惯,好了,接下来就录入一些数据吧!
先插入T_Stu:
[sql] view
plaincopyprint?
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(1,'洪磊',1,1);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(2,'兴堂',3,1);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(3,'兴湘',2,2);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(4,'孑帆',2,1);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(5,'兴华',1,1);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(6,'维瑞',1,2);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(7,'俐杰',2,2);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(8,'刘洋',3,2);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(9,'安泰',1,1);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(10,'月岑',1,1);
接着到T_Class表:
[sql] view
plaincopyprint?
INSERT INTO T_Class(Cl_id,Cl_name)VALUES(1,'初一(2)班');
INSERT INTO T_Class(Cl_id,Cl_name)VALUES(2,'初二(1)班');
INSERT INTO T_Class(Cl_id,Cl_name)VALUES(3,'初三(4)班');
最后到T_Drom表:
[sql] view
plaincopyprint?
INSERT INTO T_Drom(Do_id,Do_name)VALUES(1,'4栋');
INSERT INTO T_Drom(Do_id,Do_name)VALUES(2,'6栋');
1.内连接(INNER JOIN)
①等值连接:
连接条件中使用等于号(=)运算符来比较连接的列值,但是查询结果会列出被连接表中的所有列,包括重复列,这也是和②自然连接的不同!
例子:
[sql] view
plaincopyprint?
SELECT * FROM T_Stu INNER JOIN T_Class
ON T_Stu.Cl_id = T_Class.Cl_id
运行SQL:
②自然连接:
和等值连接类似,不过可以选择需要显示的列例子:
[sql] view
plaincopyprint?
SELECT SId AS '学生编号',SName AS '学生姓名',Cl_name AS '所在班级' FROM T_Stu INNER JOIN T_Class
ON T_Stu.Cl_id = T_Class.Cl_id
运行SQL:
③不等连接:
就是不用(=)号,而是用其他的比较运算符: <,>,<=.>=,!>,!<,<>(不等于)就是修改下=号而已,这里不讲解!
接着演示下连接多个表的写法:
[sql] view
plaincopyprint?
SELECT SId AS '学生编号',SName AS '学生姓名',
Cl_name AS '所在班级',Do_name AS '所在宿舍' FROM T_Stu
INNER JOIN T_Class ON T_Stu.Cl_id = T_Class.Cl_id
INNER JOIN T_Drom ON T_Stu.Do_id = T_Drom.Do_id
运行SQL:
上面就把三个表连接起来了,每增加一个表,只需:
添加INNER JOIN 表名 ON(匹配条件)即可!
表名太长,写起来麻烦,那么就使用别名:
[sql] view
plaincopyprint?
SELECT s.SId AS '学生编号',s.SName AS '学生姓名',
c.Cl_name AS '所在班级',d.Do_name AS '所在宿舍' FROM T_Stu s INNER JOIN T_Class c
ON s.Cl_id = c.Cl_id INNER JOIN T_Drom d
ON s.Do_id = d.Do_id
运行的效果也是一样的!
2.外连接:
外连接的语法与内连接几乎是一样的,主要区别是:对于空值的处理!外连接不需要两个表都具有匹配记录,这样可以指定某个表中的记录总是放到结果集中!
简单点就是说:返回到结果集中的不仅包含符合条件的行,还包括左表(左外连接)、右表
(右外连接)或者两个连接表(完全连接)中的所有数据行!
①左外连接:
先插入两条数据:[sql] view
plaincopyprint?
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(11,'小明',null,null);
INSERT INTO T_Stu(SId,SName,Cl_id,Do_id)VALUES(12,'小红',null,null);
接下来我们使用左外连接:
[sql] view
plaincopyprint?
SELECT s.SId AS '学生编号',s.SName AS '学生姓名',
c.Cl_id AS '班级编号',c.Cl_Name '所在班级'
FROM T_Stu AS s LEFT OUTER JOIN T_Class AS c ON
s.Cl_id = c.Cl_id
运行SQL:
②右外连接:
右外连接与左外连接相对,以右边为主表,左边为从表,其他一样!先往T_Class表中插入两条记录:
[sql] view
plaincopyprint?
INSERT INTO T_Class(Cl_id,Cl_name)VALUES(4,'高一(2)班');
INSERT INTO T_Class(Cl_id,Cl_name)VALUES(5,'高三(1)班');
接下来把左外连接中的LEFT OUTER JOIN改成RIGHT OUT JOIN即可!
[sql] view
plaincopyprint?
SELECT s.SId AS '学生编号',s.SName AS '学生姓名',
c.Cl_id AS '班级编号',c.Cl_Name '所在班级'
FROM T_Stu AS s RIGHT OUTER JOIN T_Class AS c ON
s.Cl_id = c.Cl_id
运行SQL:
③完全连接:
这个就是除了匹配的值外,左右两个表都会全部显示把上面的RIGHT OUTER JOIN该成:FULL OUTER JOIN即可!
[sql] view
plaincopyprint?
SELECT s.SId AS '学生编号',s.SName AS '学生姓名',
c.Cl_id AS '班级编号',c.Cl_Name '所在班级'
FROM T_Stu AS s FULL OUTER JOIN T_Class AS c ON
s.Cl_id = c.Cl_id
运行SQL:
3.交叉连接:
如果没有 WHERE 子句的交叉联接将产生连接所涉及的表的笛卡尔积。第一个表的行数乘以第二个表的行数等于笛卡尔积结果集的大小。
又分为两种,隐式与显式!
隐式的超简单,直接select ... From后直接加上交叉连接的表名列即可!
比如:
[sql] view
plaincopyprint?
SELECT * FROM T_Stu,T_Class
显式的:
[sql] view
plaincopyprint?
SELECT * FROM T_Stu cross join T_Class
大部分的DBMS都支持CROSS JOIN显式的交叉连接,而隐式的所有DBMS都支持!
4.自连接:
这个自连接和前面我们学的三种连接可不一样,自连接是自己对自己的!即连接关键字的两边都是同一个表!
一个形象的例子就是地区表!
创建一个简单的地区表,接着录几条数据!
建表SQL:
[sql] view
plaincopyprint?
CREATE TABLE T_City
(
CId INTEGER,
CName VARCHAR(10),
CBelong VARCHAR(10),
PRIMARY KEY (CId)
)
插入几条数据:
[sql] view
plaincopyprint?
INSERT INTO T_City(CId,CName,BId)VALUES(1,'北京',NULL);
INSERT INTO T_City(CId,CName,BId)VALUES(2,'上海',NULL);
INSERT INTO T_City(CId,CName,BId)VALUES(3,'天津',NULL);
INSERT INTO T_City(CId,CName,BId)VALUES(4,'重庆',NULL);
INSERT INTO T_City(CId,CName,BId)VALUES(5,'南京',6);
INSERT INTO T_City(CId,CName,BId)VALUES(6,'江苏',NULL);
INSERT INTO T_City(CId,CName,BId)VALUES(7,'苏州',6);
INSERT INTO T_City(CId,CName,BId)VALUES(8,'无锡',6);
INSERT INTO T_City(CId,CName,BId)VALUES(9,'广东',NULL);
INSERT INTO T_City(CId,CName,BId)VALUES(10,'揭阳',9);
接下来就到自连接了:
[sql] view
plaincopyprint?
SELECT a.CName,b.CName
FROM T_City as a INNER JOIN T_City as b
ON a.CId = b.Bid
运行自连接的SQL:
你也可以统计辖区数:
[sql] view
plaincopyprint?
SELECT a.CName,COUNT(b.CId) as '辖区数'
FROM T_City as a INNER JOIN T_City as b
ON a.CId = b.Bid
GROUP BY a.CName
运行上述SQL:
相关文章推荐
- Windows7下安装MongoDB
- sqlserver2005表转到mysql数据库
- [windows] flask - sqlite3.OperationalError: unable to open database file
- mysql数据库总是连接失败,Warning:mysql_connect() :Connection refused...
- oracle client 删除后 oci.dll 删不掉
- MongoDB 复制集模式Replica Sets
- mysql安装过程记录和后续学习
- Memcached详解
- ORACLE恢复删除表或表记录
- MySQL数据输到redis
- MySQL添加用户、删除用户与授权
- MySQL重置root用户密码的方法
- mysql主从复制及双主结构
- 15天玩转redis —— 第三篇 无敌的列表类型
- Mysql 锁粒度
- SQL 标准中的四种隔离级别
- mysql中left join中的on条件 和 where条件区别
- SQL-删除重复数据
- MySQL完全备份+增量备份
- Navicat for Mysql的操作使用