SQL 三种基本Join

Join是关系型数据库系统的重要操作之一,SQL常用Join:内联接、外联接和交叉联接等。

这里讨论一下这常用的三种连接。

测试环境:db2 v10.1, linux 

表定义:

 1 --用户
 2 CREATE TABLE USER
 3 (
 4 USERID INTEGER NOT NULL,
 5 COMPANYID INTEGER,
 6 TELNO VARCHAR(12)
 7 );
 8 
 9 --公司
10 CREATE TABLE COMPANY
11 (
12 COMPANYID INTEGER NOT NULL,
13 TELNO VARCHAR(12)
14 );

数据:

--USER

USERID      COMPANYID   TELNO       
----------- ----------- ------------
         11           2 777777      
         22           3 123456      
         33           4 567890  

--COMPANY

COMPANYID   TELNO       
----------- ------------
          2 888888   

1. inner join

[db2inst1@win ~]$ db2 "select * from user inner join company on user.companyid=company.companyid"

USERID      COMPANYID   TELNO        COMPANYID   TELNO       
----------- ----------- ------------ ----------- ------------
         11           2 777777                 2 888888      

  1 record(s) selected.

注意:内联接(Inner join)满足交换律:“A inner join B” 和 “B inner join A” 是相等的。

查看访问计划:

Optimized Statement:
-------------------
SELECT 
  Q2.USERID AS "USERID",
  Q2.COMPANYID AS "COMPANYID",
  Q2.TELNO AS "TELNO",
  Q1.COMPANYID AS "COMPANYID",
  Q1.TELNO AS "TELNO" 
FROM 
  DB2INST1.COMPANY AS Q1,
  DB2INST1.USER AS Q2 
WHERE 
  (Q2.COMPANYID = Q1.COMPANYID)

Access Plan:
-----------
    Total Cost:         13.5566
    Query Degree:        1

              Rows 
             RETURN
             (   1)
              Cost 
               I/O 
               |
                1 
             HSJOIN
             (   2)
             13.5566 
                2 
         /-----+------
        3                1 
     TBSCAN           TBSCAN
     (   3)           (   4)
     6.77858          6.77776 
        1                1 
       |                |
        3                1 
 TABLE: DB2INST1  TABLE: DB2INST1
      USER            COMPANY
       Q2               Q1

用HSJOIN的方式进行,DB2对此进行了重写。

2. outer join

外部联接保存一个或两个输入表的所有行,即使无法找到匹配联接谓词的行。

[db2inst1@win ~]$ db2 "select * from user left outer join company on user.companyid=company.companyid"

USERID      COMPANYID   TELNO        COMPANYID   TELNO       
----------- ----------- ------------ ----------- ------------
         11           2 777777                 2 888888      
         33           4 567890                 - -           
         22           3 123456                 - -           

  3 record(s) selected.
[db2inst1@win ~]$ db2 "select * from user right outer join company on user.companyid=company.companyid"

USERID      COMPANYID   TELNO        COMPANYID   TELNO       
----------- ----------- ------------ ----------- ------------
         11           2 777777                 2 888888      

  1 record(s) selected.

查看访问计划:

Optimized Statement:
-------------------
SELECT 
  Q2.USERID AS "USERID",
  Q2.COMPANYID AS "COMPANYID",
  Q2.TELNO AS "TELNO",
  Q1.COMPANYID AS "COMPANYID",
  Q1.TELNO AS "TELNO" 
FROM 
  DB2INST1.COMPANY AS Q1 
  LEFT OUTER JOIN DB2INST1.USER AS Q2 
  ON (Q2.COMPANYID = Q1.COMPANYID)

Access Plan:
-----------
    Total Cost:         13.5566
    Query Degree:        1

              Rows 
             RETURN
             (   1)
              Cost 
               I/O 
               |
                1 
             HSJOIN<
             (   2)
             13.5566 
                2 
         /-----+------
        3                1 
     TBSCAN           TBSCAN
     (   3)           (   4)
     6.77858          6.77776 
        1                1 
       |                |
        3                1 
 TABLE: DB2INST1  TABLE: DB2INST1
      USER            COMPANY
       Q2               Q1

这里也是用的HSJOIN。

3. cross join

交叉联接(cross join)执行两个表的笛卡尔积(就是把表A和表B的数据进行一个N*M的组合)。也就是说,它匹配一个表与另一个表中的每一行;我们不能通过使用ON子句在交叉联接指定谓词,虽然我们可以使用WHERE子句来实现相同的结果,这是交叉联接基本上是作为一个内部联接了。

[db2inst1@win ~]$ db2 "select * from user cross join company"

USERID      COMPANYID   TELNO        COMPANYID   TELNO       
----------- ----------- ------------ ----------- ------------
         11           2 777777                 2 888888      
         22           3 123456                 2 888888      
         33           4 567890                 2 888888      

  3 record(s) selected.

查看访问计划:

Optimized Statement:
-------------------
SELECT 
  Q2.USERID AS "USERID",
  Q2.COMPANYID AS "COMPANYID",
  Q2.TELNO AS "TELNO",
  Q1.COMPANYID AS "COMPANYID",
  Q1.TELNO AS "TELNO" 
FROM 
  DB2INST1.COMPANY AS Q1,
  DB2INST1.USER AS Q2

Access Plan:
-----------
    Total Cost:         13.5563
    Query Degree:        1

              Rows 
             RETURN
             (   1)
              Cost 
               I/O 
               |
                3 
             NLJOIN
             (   2)
             13.5563 
                2 
         /-----+------
        1                3 
     TBSCAN           TBSCAN
     (   3)           (   4)
     6.77776          6.77858 
        1                1 
       |                |
        1                3 
 TABLE: DB2INST1  TABLE: DB2INST1
     COMPANY           USER
       Q1               Q2

看到这里使用的是NLJOIN。

原文地址:https://www.cnblogs.com/jackhub/p/3170780.html