Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql “与”的区别是什么;“内部连接”;及;外部连接“;?_Sql_Database_Join_Inner Join_Outer Join - Fatal编程技术网

Sql “与”的区别是什么;“内部连接”;及;外部连接“;?

Sql “与”的区别是什么;“内部连接”;及;外部连接“;?,sql,database,join,inner-join,outer-join,Sql,Database,Join,Inner Join,Outer Join,另外,左连接、右连接和完全连接如何适应?如果连接的另一侧(右侧)有匹配的记录,则内部连接仅显示行 (左)外部联接在左侧显示每条记录的行,即使联接的另一侧(右)没有匹配的行。如果没有匹配的行,则另一侧(右侧)的列将显示空值。内部联接要求联接表中存在具有相关ID的记录 外部联接将返回左侧的记录,即使右侧不存在任何记录 例如,您有一个Orders和一个OrderDetails表。它们由一个“OrderID”关联 订单 医嘱ID 客户名称 订单详细信息 OrderDetailID 医嘱ID 产品名

另外,
左连接
右连接
完全连接
如何适应?

如果连接的另一侧(右侧)有匹配的记录,则内部连接仅显示行


(左)外部联接在左侧显示每条记录的行,即使联接的另一侧(右)没有匹配的行。如果没有匹配的行,则另一侧(右侧)的列将显示空值。

内部联接要求联接表中存在具有相关ID的记录

外部联接将返回左侧的记录,即使右侧不存在任何记录

例如,您有一个Orders和一个OrderDetails表。它们由一个“OrderID”关联

订单

  • 医嘱ID
  • 客户名称
订单详细信息

  • OrderDetailID
  • 医嘱ID
  • 产品名称
  • 数量
  • 价格
请求

SELECT Orders.OrderID, Orders.CustomerName
  FROM Orders 
 INNER JOIN OrderDetails
    ON Orders.OrderID = OrderDetails.OrderID
将仅返回OrderDetails表中也包含某些内容的订单

如果您将其更改为外部左连接

SELECT Orders.OrderID, Orders.CustomerName
  FROM Orders 
  LEFT JOIN OrderDetails
    ON Orders.OrderID = OrderDetails.OrderID
然后它将从Orders表返回记录,即使它们没有OrderDetails记录


通过添加where子句(如
where OrderDetails.OrderID为NULL

),您可以使用此命令查找没有任何OrderDetails指示可能孤立订单的订单,前提是您在没有重复项的列上加入,这是一种非常常见的情况:

  • A和B的内部连接给出相交B的结果,即相交的内部部分

  • A和B的外部连接给出了并集B的结果,即维恩图并集的外部部分

示例

假设您有两个表,每个表只有一列,数据如下:

A    B
-    -
1    3
2    4
3    5
4    6
注意,(1,2)是A所特有的,(3,4)是常见的,(5,6)是B所特有的

内部联接

使用任何一个等价查询的内部联接都会给出两个表的交集,即它们共有的两行

select * from a INNER JOIN b on a.a = b.b;
select a.*, b.*  from a,b where a.a = b.b;

a | b
--+--
3 | 3
4 | 4
左外连接

左外部联接将给出A中的所有行,以及B中的任何公共行

select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.*  from a,b where a.a = b.b(+);

a |  b
--+-----
1 | null
2 | null
3 |    3
4 |    4
右外连接

右外部联接将给出B中的所有行,以及A中的任何公共行

select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.*  from a,b where a.a(+) = b.b;

a    |  b
-----+----
3    |  3
4    |  4
null |  5
null |  6
完全外部联接

一个完整的外部联接将提供A和B的并集,即A中的所有行和B中的所有行。如果A中的某些内容在B中没有相应的基准,则B部分为空,反之亦然

select * from a FULL OUTER JOIN b on a.a = b.b;

 a   |  b
-----+-----
   1 | null
   2 | null
   3 |    3
   4 |    4
null |    6
null |    5

内部联接
要求在比较两个表时至少存在匹配项。例如,表A和表B表示A٨B(交叉点B)

左外连接
左连接
是相同的。它给出了两个表中匹配的所有记录以及左表的所有可能性

类似地,
右外部联接
右联接
是相同的。它给出了两个表中匹配的所有记录以及正确表的所有可能性

SELECT e.id , e.name , p.phone_num FROM employees AS e LEFT JOIN phone_numbers_employees AS p ON e.id = p.emp_id;

完全联接
左外部联接
右外部联接
的组合,没有重复。

使用
内部联接
返回两个表中匹配的所有行。i、 e.在结果表中,所有行和列都将具有值

在外部联接中,生成的表可能有空列。外部联接可以是
左侧
右侧

左外部联接
返回第一个表中的所有行,即使第二个表中没有匹配项

右外部联接
返回第二个表中的所有行,即使第一个表中没有匹配项。

简单地说:

内部联接仅检索匹配的行

然而,外部联接从一个表和其他表中的所有行检索匹配的行……结果取决于您使用的是哪一行:

  • :匹配右表中的行和左表中的所有行

  • :匹配左表中的行和右表中的所有行或

  • Full:所有表中的所有行。有没有比赛并不重要


    • 在其他答案中,我看不到关于性能和优化器的太多细节

      有时最好知道只有
      内部联接
      是关联的,这意味着优化器有最多的选项来处理它。它可以对连接顺序进行重新排序,以便更快地保持相同的结果。优化器可以使用最多的连接模式

      通常,最好尝试使用
      内部联接
      ,而不是使用不同类型的联接。(当然,如果考虑到预期结果集可能的话。)

      关于这种奇怪的关联行为,这里有几个很好的例子和解释:

      内部连接 仅检索匹配的行,即,
      A与B相交

      SELECT *
      FROM dbo.Students S
      INNER JOIN dbo.Advisors A
          ON S.Advisor_ID = A.Advisor_ID
      


      左外连接 选择第一个表中的所有记录,以及第二个表中的所有记录 与联接键匹配的表

      SELECT *
      FROM dbo.Students S
      LEFT JOIN dbo.Advisors A
          ON S.Advisor_ID = A.Advisor_ID
      
      SELECT *
      FROM dbo.Students S
      FULL JOIN dbo.Advisors A
          ON S.Advisor_ID = A.Advisor_ID
      


      完全外接 选择第二个表中的所有记录,以及第一个表中的所有记录 与联接键匹配的表

      SELECT *
      FROM dbo.Students S
      LEFT JOIN dbo.Advisors A
          ON S.Advisor_ID = A.Advisor_ID
      
      SELECT *
      FROM dbo.Students S
      FULL JOIN dbo.Advisors A
          ON S.Advisor_ID = A.Advisor_ID
      


      工具书类

      内部连接。

      联接是将两个表中的行组合在一起。内部联接尝试根据查询中指定的条件匹配这两个表,并且只返回匹配的行。如果联接中第一个表中的一行与第二个表中的两行匹配,则结果中将返回两行。我
      1.Take All records from left Table
      2.for(each record in right table,) {
          if(Records from left & right table matching on primary & foreign key){
             use their values as it is as result of join at the right side for 2nd table.
          } else {
             put value NULL values in that particular record as result of join at the right side for 2nd table.
          }
        }
      
      employees : id , name 
      
      phone_numbers_employees : id , phone_num , emp_id   
      
      SELECT e.id , e.name , p.phone_num FROM employees AS e INNER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
      
      SELECT e.id , e.name , p.phone_num FROM employees AS e LEFT JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
      
      SELECT e.id , e.name , p.phone_num FROM employees AS e OUTER JOIN phone_numbers_employees AS p ON e.id = p.emp_id;
      
      --[table1]               --[table2]
      id | name                id | name
      ---+-------              ---+-------
      1  | a1                  1  | a2
      2  | b1                  3  | b2
      
      SELECT * FROM table1, table2
      --[OR]
      SELECT * FROM table1 CROSS JOIN table2
      
      --[Results:]
      id | name | id | name 
      ---+------+----+------
      1  | a1   | 1  | a2
      1  | a1   | 3  | b2
      2  | b1   | 1  | a2
      2  | b1   | 3  | b2
      
      SELECT * FROM table1, table2 WHERE table1.id = table2.id
      --[OR]
      SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id
      
      --[Results:]
      id | name | id | name 
      ---+------+----+------
      1  | a1   | 1  | a2
      
      SELECT * FROM table1, table2 WHERE table1.id = table2.id 
      UNION ALL
      SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
      --[OR]
      SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
      
      --[Results:]
      id | name | id   | name 
      ---+------+------+------
      1  | a1   | 1    | a2
      2  | b1   | Null | Null
      
      SELECT * FROM table1, table2 WHERE table1.id = table2.id
      UNION ALL
      SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
      UNION ALL
      SELECT Null, Null, * FROM table2 WHERE Not table2.id In (SELECT id FROM table1)
      --[OR] (recommended for SQLite)
      SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
      UNION ALL
      SELECT * FROM table2 LEFT JOIN table1 ON table2.id = table1.id
      WHERE table1.id IS NULL
      --[OR]
      SELECT * FROM table1 FULL OUTER JOIN table2 On table1.id = table2.id
      
      --[Results:]
      id   | name | id   | name 
      -----+------+------+------
      1    | a1   | 1    | a2
      2    | b1   | Null | Null
      Null | Null | 3    | b2
      
      SELECT
        e1.emp_name,
        e2.emp_salary    
      FROM emp1 e1
      INNER JOIN emp2 e2
        ON e1.emp_id = e2.emp_id
      
      SELECT
        e1.emp_name,
        e2.emp_salary    
      FROM emp1 e1
      FULL OUTER JOIN emp2 e2
        ON e1.emp_id = e2.emp_id
      
      SELECT * 
      FROM   tablea a 
             INNER JOIN tableb b 
                     ON a.primary_key = b.foreign_key 
             INNER JOIN tablec c 
                     ON b.primary_key = c.foreign_key 
      
      empid   name    dept_id salary
      1       Rob     1       100
      2       Mark    1       300
      3       John    2       100
      4       Mary    2       300
      5       Bill    3       700
      6       Jose    6       400
      
      deptid  name
      1       IT
      2       Accounts
      3       Security
      4       HR
      5       R&D
      
      Select a.empid, a.name, b.name as dept_name
      FROM emp a
      JOIN department b
      ON a.dept_id = b.deptid
      ;
      
      empid   name    dept_name
      1       Rob     IT
      2       Mark    IT
      3       John    Accounts
      4       Mary    Accounts
      5       Bill    Security
      
      Select a.empid, a.name, b.name as dept_name
      FROM emp a
      LEFT JOIN department b
      ON a.dept_id = b.deptid
      ;
      
      empid   name    dept_name
      1       Rob     IT
      2       Mark    IT
      3       John    Accounts
      4       Mary    Accounts
      5       Bill    Security
      6       Jose    
      
      SELECT *
        FROM citizen
       CROSS JOIN postalcode
      
      SELECT *
        FROM citizen    c
        JOIN postalcode p ON c.postal = p.postal
      
      SELECT *
        FROM citizen         c
        LEFT JOIN postalcode p ON c.postal = p.postal
      
      CREATE TABLE citizen (id      NUMBER,
                            name    VARCHAR2(20),
                            postal  NUMBER,  -- <-- could do with a redesign to postalcode.id instead.
                            leader  NUMBER);
      
      CREATE TABLE postalcode (id      NUMBER,
                               postal  NUMBER,
                               city    VARCHAR2(20),
                               area    VARCHAR2(20));
      
      INSERT INTO citizen (id, name, postal, leader)
                    SELECT 1, 'Smith', 2200,  null FROM DUAL
              UNION SELECT 2, 'Green', 31006, 1    FROM DUAL
              UNION SELECT 3, 'Jensen', 623,  1    FROM DUAL;
      
      INSERT INTO postalcode (id, postal, city, area)
                       SELECT 1, 2200,     'BigCity',         'Geancy'  FROM DUAL
                 UNION SELECT 2, 31006,    'SmallTown',       'Snizkim' FROM DUAL
                 UNION SELECT 3, 31006,    'Settlement',      'Moon'    FROM DUAL  -- <-- Uuh-uhh.
                 UNION SELECT 4, 78567390, 'LookoutTowerX89', 'Space'   FROM DUAL;
      
      SELECT *
        FROM citizen          c
        CROSS JOIN postalcode p
       WHERE c.postal = p.postal -- < -- The WHERE condition is limiting the resulting rows
      
      SELECT *
        FROM citizen    c
        JOIN postalcode p ON 1 = 1  -- < -- The ON condition makes it a CROSS JOIN
      
      SELECT *
        FROM citizen         c
        LEFT JOIN postalcode p ON 1 = 1 -- < -- The ON condition makes it a CROSS JOIN
      
      SELECT *
        FROM citizen         c
        LEFT JOIN postalcode p ON c.postal = p.postal
       WHERE p.postal IS NOT NULL -- < -- removed the row where there's no mathcing result from postalcode
      
      SELECT *
        FROM citizen c1
        JOIN citizen c2 ON c1.id = c2.leader
      
      SELECT *
        FROM citizen          c
       CROSS JOIN postalcode  p
       WHERE c.name = 'Smith'
         AND p.area = 'Moon';
      
      SELECT *
        FROM citizen          c
       CROSS JOIN postalcode  p
       WHERE c.name = 'Smith'
      INTERSECT
      SELECT *
        FROM citizen          c
       CROSS JOIN postalcode  p
       WHERE p.area = 'Moon';
      
      SELECT *
        FROM citizen          c
       CROSS JOIN postalcode  p
       WHERE c.name = 'Smith'
      UNION
      SELECT *
        FROM citizen          c
       CROSS JOIN postalcode  p
       WHERE p.area = 'Moon';
      
      SELECT *
        FROM citizen          c
       CROSS JOIN postalcode  p
       WHERE c.name = 'Smith'
         OR p.area = 'Moon';
      
      SELECT *
        FROM citizen
       WHERE name = 'Smith'
      
      SELECT *
        FROM postalcode
       WHERE area = 'Moon';
      
      ORA-01790: expression must have same datatype as corresponding expression
      
       human_name | cat_name
      ------------+-----------
       Abe        | Axel
       Jen        | Jellybean
       Jen        | Juniper
      
       human_name | cat_name
      ------------+-----------
       Abe        | Axel
       Ann        | [NULL]
       Ben        | [NULL]
       Jen        | Jellybean
       Jen        | Juniper
       [NULL]     | Bitty
      
       human_name | cat_name
      ------------+-----------
       Abe        | Axel
       Ann        | [NULL]
       Ben        | [NULL]
       Jen        | Jellybean
       Jen        | Juniper
      
       human_name | cat_name
      ------------+-----------
       Abe        | Axel
       Jen        | Jellybean
       Jen        | Juniper
       [NULL]     | Bitty