全部產品
Search
文件中心

PolarDB:表之間的聯結

更新時間:Sep 13, 2024

查詢可以同時訪問多個表,或訪問同一表時同時處理該表中的多行。同時訪問同一或不同表中的多行的查詢稱為聯結查詢。

例如,假設您希望在此樣本資料庫基礎上,列出所有員工記錄以及相關部門的名稱和地址。為此,您需要將emp表中每行的deptno列與dept表中所有行的deptno列進行比較,然後選擇這些值匹配的行。這可以通過以下查詢實現:

SELECT emp.ename, emp.sal, dept.deptno, dept.dname, dept.loc FROM emp, dept WHERE emp.deptno = dept.deptno ORDER BY deptno;

返回結果如下:

 ename  |   sal   | deptno |   dname    |   loc
--------+---------+--------+------------+----------
 MILLER | 1300.00 |     10 | ACCOUNTING | NEW YORK
 CLARK  | 2450.00 |     10 | ACCOUNTING | NEW YORK
 KING   | 5000.00 |     10 | ACCOUNTING | NEW YORK
 SCOTT  | 3000.00 |     20 | RESEARCH   | DALLAS
 JONES  | 2975.00 |     20 | RESEARCH   | DALLAS
 SMITH  |  800.00 |     20 | RESEARCH   | DALLAS
 ADAMS  | 1100.00 |     20 | RESEARCH   | DALLAS
 FORD   | 3000.00 |     20 | RESEARCH   | DALLAS
 WARD   | 1250.00 |     30 | SALES      | CHICAGO
 TURNER | 1500.00 |     30 | SALES      | CHICAGO
 ALLEN  | 1600.00 |     30 | SALES      | CHICAGO
 BLAKE  | 2850.00 |     30 | SALES      | CHICAGO
 MARTIN | 1250.00 |     30 | SALES      | CHICAGO
 JAMES  |  950.00 |     30 | SALES      | CHICAGO
(14 rows)

觀察有關結果集的兩件事情:

  • 列出按表名限定的輸出資料行更可取,而不是使用*或省略資格,如下所示:

    SELECT ename, sal, dept.deptno, dname, loc FROM emp, dept WHERE emp.deptno = dept.deptno;

    由於所有列具有不同的名稱(deptno除外,因此必須限定它),剖析器將自動尋找它們屬於哪個表,但最好在聯結查詢中完全限定列名稱。

    到目前為止,上面所示的那種聯結查詢也可以編寫為以下替代形式:

    SELECT emp.ename, emp.sal, dept.deptno, dept.dname, dept.loc FROM emp INNER JOIN dept ON emp.deptno = dept.deptno ORDER BY deptno;

    此文法不像上述文法那樣常用,但我們在此處顯示它是為了協助您理解以下主題。

  • 沒有部門40的結果行。這是因為emp表中沒有部門40的匹配條目,因此聯結忽略了dept表中不匹配的行。現在我們將瞭解如何在結果中獲得部門40記錄,即使沒有匹配的員工。

    • 我們希望查詢掃描dept表中的每行來找到匹配的emp行。如果沒有找到匹配的行,我們希望使用一些“空”值來替代emp表的列。這種查詢稱為外部聯結。(到目前為止,我們看到的聯結是內部聯結。)外部聯結命令如下所示:

      SELECT emp.ename, emp.sal, dept.deptno, dept.dname, dept.loc FROM dept LEFT OUTER JOIN emp ON emp.deptno = dept.deptno ORDER BY deptno;

      返回結果如下:

       ename  |   sal   | deptno |   dname    |   loc
      --------+---------+--------+------------+----------
       MILLER | 1300.00 |     10 | ACCOUNTING | NEW YORK
       CLARK  | 2450.00 |     10 | ACCOUNTING | NEW YORK
       KING   | 5000.00 |     10 | ACCOUNTING | NEW YORK
       SCOTT  | 3000.00 |     20 | RESEARCH   | DALLAS
       JONES  | 2975.00 |     20 | RESEARCH   | DALLAS
       SMITH  |  800.00 |     20 | RESEARCH   | DALLAS
       ADAMS  | 1100.00 |     20 | RESEARCH   | DALLAS
       FORD   | 3000.00 |     20 | RESEARCH   | DALLAS
       WARD   | 1250.00 |     30 | SALES      | CHICAGO
       TURNER | 1500.00 |     30 | SALES      | CHICAGO
       ALLEN  | 1600.00 |     30 | SALES      | CHICAGO
       BLAKE  | 2850.00 |     30 | SALES      | CHICAGO
       MARTIN | 1250.00 |     30 | SALES      | CHICAGO
       JAMES  |  950.00 |     30 | SALES      | CHICAGO
              |         |     40 | OPERATIONS | BOSTON
      (15 rows)

      此查詢稱為左方外部聯結,因為聯結運算子左側提及的表將在輸出中具有其每一行至少一次,而右側的表將只具有與左側表的某行匹配的那些行輸出。當選擇的左側錶行沒有右側表匹配時,將使用NULL替代右側表列。

      外部聯結的替代文法是在WHERE子句中的聯結條件中使用外部聯結運算子“(+)”。對於應使用NULL值替代其不匹配的行的表,將外部聯結運算子放在該表的列名稱之後。因此,對於dept表中在emp表中沒有匹配行的所有行,PolarDB PostgreSQL版(相容Oracle)將為包含emp的列的任何挑選清單運算式返回NULL。因此,上述樣本可重新編寫為:

      SELECT emp.ename, emp.sal, dept.deptno, dept.dname, dept.loc FROM dept, emp WHERE emp.deptno(+) = dept.deptno ORDER BY deptno;

      返回結果如下:

       ename  |   sal   | deptno |   dname    |   loc
      --------+---------+--------+------------+----------
       MILLER | 1300.00 |     10 | ACCOUNTING | NEW YORK
       CLARK  | 2450.00 |     10 | ACCOUNTING | NEW YORK
       KING   | 5000.00 |     10 | ACCOUNTING | NEW YORK
       SCOTT  | 3000.00 |     20 | RESEARCH   | DALLAS
       JONES  | 2975.00 |     20 | RESEARCH   | DALLAS
       SMITH  |  800.00 |     20 | RESEARCH   | DALLAS
       ADAMS  | 1100.00 |     20 | RESEARCH   | DALLAS
       FORD   | 3000.00 |     20 | RESEARCH   | DALLAS
       WARD   | 1250.00 |     30 | SALES      | CHICAGO
       TURNER | 1500.00 |     30 | SALES      | CHICAGO
       ALLEN  | 1600.00 |     30 | SALES      | CHICAGO
       BLAKE  | 2850.00 |     30 | SALES      | CHICAGO
       MARTIN | 1250.00 |     30 | SALES      | CHICAGO
       JAMES  |  950.00 |     30 | SALES      | CHICAGO
              |         |     40 | OPERATIONS | BOSTON
      (15 rows)
    • 我們還可以使表與自身聯結。這稱為自我聯結。例如,假設我們希望尋找每個員工的姓名以及該員工的經理的姓名。因此我們需要將每個emp行的mgr列與所有其他emp行的empno列進行比較。

      SELECT e1.ename || ' works for ' || e2.ename AS "Employees and their Managers" FROM emp e1, emp e2 WHERE e1.mgr = e2.empno;

      返回結果如下:

       Employees and their Managers
      ------------------------------
       FORD works for JONES
       SCOTT works for JONES
       WARD works for BLAKE
       TURNER works for BLAKE
       MARTIN works for BLAKE
       JAMES works for BLAKE
       ALLEN works for BLAKE
       MILLER works for CLARK
       ADAMS works for SCOTT
       CLARK works for KING
       BLAKE works for KING
       JONES works for KING
       SMITH works for FORD
      (13 rows)

      在這裡,emp表已重新標記為e1以在挑選清單和聯結條件中表示員工行,還重新標記為e2以在挑選清單和聯結條件中表示擔任經理的匹配的員工行。這些類型的別名可用於其他查詢以減少輸入,例如:

      SELECT e.ename, e.mgr, d.deptno, d.dname, d.loc FROM emp e, dept d WHERE e.deptno = d.deptno ORDER BY deptno;

      返回結果如下,將相當頻繁地遇到這種樣式的縮寫。

       ename  | mgr  | deptno |   dname    |   loc
      --------+------+--------+------------+----------
       MILLER | 7782 |     10 | ACCOUNTING | NEW YORK
       CLARK  | 7839 |     10 | ACCOUNTING | NEW YORK
       KING   |      |     10 | ACCOUNTING | NEW YORK
       SCOTT  | 7566 |     20 | RESEARCH   | DALLAS
       JONES  | 7839 |     20 | RESEARCH   | DALLAS
       SMITH  | 7902 |     20 | RESEARCH   | DALLAS
       ADAMS  | 7788 |     20 | RESEARCH   | DALLAS
       FORD   | 7566 |     20 | RESEARCH   | DALLAS
       WARD   | 7698 |     30 | SALES      | CHICAGO
       TURNER | 7698 |     30 | SALES      | CHICAGO
       ALLEN  | 7698 |     30 | SALES      | CHICAGO
       BLAKE  | 7839 |     30 | SALES      | CHICAGO
       MARTIN | 7698 |     30 | SALES      | CHICAGO
       JAMES  | 7698 |     30 | SALES      | CHICAGO
      (14 rows)