zoukankan      html  css  js  c++  java
  • 全面解析SQL SERVER 的左右内连接

    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;

     

    得到的结果都是例如以下:

    结论:假设两个表的记录数是一样的。并且主键的值也是一样的话,这个时候用什么连接他们的结果都是一样的。

     

     

    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

     

    返回的是右表,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 NAME SCORE
    1 张三 90
    2 李四 95
    3 王五 98

    返回的是左右两个表都有的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;

    1 张三 90
    1 张三 95
    1 张三 98
    1 张三 99
    2 李四 NULL
    3 王五 NULL
    4 刘六 NULL

    得出的结果集记录数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;

    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

     

    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;

    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

    在这样的情况下得出的结果集都是14条记录。

     

    结论: 不管左,右连接得到的结果集的记录数肯定是大于等于主表的记录数的,而内连接的结果集能够是小于,等于,大于连接的表的记录数的。

    左。右还是内连接表的一个重要的用处:能够横行的扩展一个表。能够得到一个有很多其它属性的新的表。

    UNION 能够纵向的添加一个表的记录行数。

  • 相关阅读:
    springboot整合mybatis
    springboot配置mvc拦截器
    ORA-65048:在可插入数据库PDBORCL中处理当前DDL语句时出错 ORA-00959:表空间‘MMMM’不存在
    SI Unit 国际标准单位
    java学习的第二阶段总结
    java学习的第一阶段总结
    vmware学习笔记
    java当中的语法糖
    jvm系统学习笔记
    java中Direct Memory堆外内存
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/7309211.html
Copyright © 2011-2022 走看看