全面解析SQL SERVER 的左右内连接
2014-10-25 21:57
211 查看
SQL SERVER数据库的三种常用连接解析:
这里先给出一个官方的解释:
left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录
right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录
inner join(等值连接) 只返回两个表中联结字段相等的行
USE [BI]
GO
DROP TABLE BI.dbo.TABLE_ONE;
GO
DROP TABLE BI.dbo.TABLE_TWO;
GO
CREATE TABLE BI.dbo.TABLE_ONE(
[ID] [int] NOT NULL,
[NAME] [nvarchar](50) NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE BI.dbo.TABLE_TWO(
[ID] [int] NOT NULL,
[SCORE] [int] NOT NULL
) ON [PRIMARY]
GO
1, 如果我两个表分别插入的是如下的信息:
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'张三');
INSERT INTO BI.DBO.TABLE_ONE VALUES(2,'李四');
INSERT INTO BI.DBO.TABLE_ONE VALUES(3,'王五');
GO
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,90);
INSERT INTO BI.DBO.TABLE_TWO VALUES(2,95);
INSERT INTO BI.DBO.TABLE_TWO VALUES(3,98);
GO
在这种情况下:其实左连接和右连接,内连接的结果都是一样的:
--左连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE LEFT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
--右连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE RIGHT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
--内连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE INNER JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
得到的结果都是如下:
![](http://img.blog.csdn.net/20141025203946500?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2F0ZXJ4Y2ZnMzA0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
结论:如果两个表的记录数是一样的,而且主键的值也是一样的话,这个时候用什么连接他们的结果都是一样的。
2, 如果我两个表分别插入的是如下的信息:
truncate table BI.DBO.TABLE_ONE;
truncate table BI.DBO.TABLE_TWO;
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'张三');
INSERT INTO BI.DBO.TABLE_ONE VALUES(2,'李四');
INSERT INTO BI.DBO.TABLE_ONE VALUES(3,'王五');
INSERT INTO BI.DBO.TABLE_ONE VALUES(4,'刘六');
GO
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,90);
INSERT INTO BI.DBO.TABLE_TWO VALUES(2,95);
INSERT INTO BI.DBO.TABLE_TWO VALUES(3,98);
INSERT INTO BI.DBO.TABLE_TWO VALUES(5,99);
GO
--左连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE LEFT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
![](http://img.blog.csdn.net/20141025210000506?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2F0ZXJ4Y2ZnMzA0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
返回的是左表的4条记录,其中左边ID=4 的在右表中存在连接的,所有右表对应的SCORE的值返回的是NULL。
--右连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE RIGHT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
返回的是右表,TABLE_TWO的4条记录相应的记录,其中TABLE_TWO有ID=5 的的记录,但是TABLE_ONE里没有,则返回NULL。
--内连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE INNER JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
返回的是左右两个表都有的ID:1,2,3 所以返回的是3条共有的记录值 。
结论:如果两个表是按照主键进行连接的话,左连接的话返回的记录集肯定是等于左表返回的记录数;右连接的话记录集肯定是等于右表返回的记录数;内连接就返回两个表都存在的记录。
上面都是以主键为连接条件的,对于左或右连接来说,得到的连接结果集肯定是等于连接中主表(左或右表)的记录数的。对于内连接,则返回的是两个表中都有的交集的记录数。下面来介绍一下不是按照主键来连接的情况下,这个时候最坏的记录数就是笛卡尔积个记录数。
3, 如果我两个表分别插入的是如下的信息:
truncate table BI.DBO.TABLE_ONE;
truncate table BI.DBO.TABLE_TWO;
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'张三');
INSERT INTO BI.DBO.TABLE_ONE VALUES(2,'李四');
INSERT INTO BI.DBO.TABLE_ONE VALUES(3,'王五');
INSERT INTO BI.DBO.TABLE_ONE VALUES(4,'刘六');
GO
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,90);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,95);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,98);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,99);
GO
--左连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE LEFT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
得出的结果集记录数7是大于主表左边4条记录的。
--右连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE RIGHT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
--内连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE INNER JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
4,下面就是极端的情况下,产生的是笛卡尔积。即两个表的记录数相乘个记录数。
truncate table BI.DBO.TABLE_ONE;
truncate table BI.DBO.TABLE_TWO;
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'张三');
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'李四');
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'王五');
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'刘六');
GO
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,90);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,95);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,98);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,99);
GO
--左连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE LEFT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
--右连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE RIGHT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
--内连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE INNER JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
在这种情况下得出的结果集都是14条记录。
结论: 无论左,右连接得到的结果集的记录数肯定是大于等于主表的记录数的,而内连接的结果集可以是小于,等于,大于连接的表的记录数的。
左,右还是内连接表的一个重要的用处:可以横行的扩展一个表,可以得到一个有更多属性的新的表。
UNION 可以纵向的增加一个表的记录行数。
这里先给出一个官方的解释:
left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录
right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录
inner join(等值连接) 只返回两个表中联结字段相等的行
USE [BI]
GO
DROP TABLE BI.dbo.TABLE_ONE;
GO
DROP TABLE BI.dbo.TABLE_TWO;
GO
CREATE TABLE BI.dbo.TABLE_ONE(
[ID] [int] NOT NULL,
[NAME] [nvarchar](50) NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE BI.dbo.TABLE_TWO(
[ID] [int] NOT NULL,
[SCORE] [int] NOT NULL
) ON [PRIMARY]
GO
1, 如果我两个表分别插入的是如下的信息:
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'张三');
INSERT INTO BI.DBO.TABLE_ONE VALUES(2,'李四');
INSERT INTO BI.DBO.TABLE_ONE VALUES(3,'王五');
GO
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,90);
INSERT INTO BI.DBO.TABLE_TWO VALUES(2,95);
INSERT INTO BI.DBO.TABLE_TWO VALUES(3,98);
GO
在这种情况下:其实左连接和右连接,内连接的结果都是一样的:
--左连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE LEFT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
--右连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE RIGHT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
--内连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE INNER JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
得到的结果都是如下:
结论:如果两个表的记录数是一样的,而且主键的值也是一样的话,这个时候用什么连接他们的结果都是一样的。
2, 如果我两个表分别插入的是如下的信息:
truncate table BI.DBO.TABLE_ONE;
truncate table BI.DBO.TABLE_TWO;
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'张三');
INSERT INTO BI.DBO.TABLE_ONE VALUES(2,'李四');
INSERT INTO BI.DBO.TABLE_ONE VALUES(3,'王五');
INSERT INTO BI.DBO.TABLE_ONE VALUES(4,'刘六');
GO
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,90);
INSERT INTO BI.DBO.TABLE_TWO VALUES(2,95);
INSERT INTO BI.DBO.TABLE_TWO VALUES(3,98);
INSERT INTO BI.DBO.TABLE_TWO VALUES(5,99);
GO
--左连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE LEFT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
返回的是左表的4条记录,其中左边ID=4 的在右表中存在连接的,所有右表对应的SCORE的值返回的是NULL。
--右连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE RIGHT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
1 | 张三 | 90 |
2 | 李四 | 95 |
3 | 王五 | 98 |
NULL | NULL | 99 |
--内连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE INNER JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
ID | NAME | SCORE |
1 | 张三 | 90 |
2 | 李四 | 95 |
3 | 王五 | 98 |
结论:如果两个表是按照主键进行连接的话,左连接的话返回的记录集肯定是等于左表返回的记录数;右连接的话记录集肯定是等于右表返回的记录数;内连接就返回两个表都存在的记录。
上面都是以主键为连接条件的,对于左或右连接来说,得到的连接结果集肯定是等于连接中主表(左或右表)的记录数的。对于内连接,则返回的是两个表中都有的交集的记录数。下面来介绍一下不是按照主键来连接的情况下,这个时候最坏的记录数就是笛卡尔积个记录数。
3, 如果我两个表分别插入的是如下的信息:
truncate table BI.DBO.TABLE_ONE;
truncate table BI.DBO.TABLE_TWO;
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'张三');
INSERT INTO BI.DBO.TABLE_ONE VALUES(2,'李四');
INSERT INTO BI.DBO.TABLE_ONE VALUES(3,'王五');
INSERT INTO BI.DBO.TABLE_ONE VALUES(4,'刘六');
GO
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,90);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,95);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,98);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,99);
GO
--左连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE LEFT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
1 | 张三 | 90 |
1 | 张三 | 95 |
1 | 张三 | 98 |
1 | 张三 | 99 |
2 | 李四 | NULL |
3 | 王五 | NULL |
4 | 刘六 | NULL |
--右连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE RIGHT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
1 | 张三 | 90 |
1 | 张三 | 95 |
1 | 张三 | 98 |
1 | 张三 | 99 |
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE INNER JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
1 | 张三 | 90 |
1 | 张三 | 95 |
1 | 张三 | 98 |
1 | 张三 | 99 |
truncate table BI.DBO.TABLE_ONE;
truncate table BI.DBO.TABLE_TWO;
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'张三');
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'李四');
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'王五');
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'刘六');
GO
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,90);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,95);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,98);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,99);
GO
--左连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE LEFT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
--右连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE RIGHT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
--内连接
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE INNER JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
1 | 张三 | 90 |
1 | 张三 | 95 |
1 | 张三 | 98 |
1 | 张三 | 99 |
1 | 李四 | 90 |
1 | 李四 | 95 |
1 | 李四 | 98 |
1 | 李四 | 99 |
1 | 王五 | 90 |
1 | 王五 | 95 |
1 | 王五 | 98 |
1 | 王五 | 99 |
1 | 刘六 | 90 |
1 | 刘六 | 95 |
1 | 刘六 | 98 |
1 | 刘六 | 99 |
结论: 无论左,右连接得到的结果集的记录数肯定是大于等于主表的记录数的,而内连接的结果集可以是小于,等于,大于连接的表的记录数的。
左,右还是内连接表的一个重要的用处:可以横行的扩展一个表,可以得到一个有更多属性的新的表。
UNION 可以纵向的增加一个表的记录行数。
相关文章推荐
- 全面解析SQL SERVER 的左右内连接
- sql server 左右连接 内外连接
- 浅谈 sql server 左右连接和全连接
- ibm全面解析esb 助企业soa连接畅通无阻
- ASP连接sql server实例解析
- ASP连接sql server实例解析
- SQL Server 连接问题案例解析(1)
- (转)ASP连接sql server实例解析
- ASP连接sql server实例解析
- ASP连接sql server实例解析
- ASP连接sql server实例解析
- SQL Server中的三种物理连接图文解析:Loop Join,Merge Join,Hash Join
- ASP连接sql server实例解析
- ASP连接sql server实例解析
- SQL Server 连接问题案例解析(1)
- 『JSP学习——全面解析JDBC(7)』
- SQL Server连接中的三个最常见错误:
- .net中webform和winform连接sql server 2000数据库的c#操作类
- 『JSP学习——全面解析JDBC(5)』
- [转]全面解析世界杀毒软件之间的关系