-- INNER JOIN
SELECT * FROM emp JOIN dept ON emp.deptno = dept.deptno;
-- LEFT OUTER JOIN:保留 emp 全部
SELECT * FROM emp LEFT OUTER JOIN dept ON emp.deptno = dept.deptno;
-- RIGHT OUTER JOIN:保留 dept 全部
SELECT * FROM emp RIGHT OUTER JOIN dept ON emp.deptno = dept.deptno;
-- FULL OUTER JOIN:保留雙方全部
SELECT * FROM emp FULL OUTER JOIN dept ON emp.deptno = dept.deptno;
連接條件使用非等號運算子:>、<、>=、<=、BETWEEN ... AND ...、!= 等。常用於**區間匹配**、**範圍歸類**。
DESC salgrade;
-- GRADE LOSAL HISAL
-- 1 700 1200
-- 2 1201 1400
-- 3 1401 2000
-- 4 2001 3000
-- 5 3001 9999
SELECT e.empno, e.ename, e.sal, s.grade
FROM emp e
JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal;
邏輯:員工薪資落在某等級區間內,即歸屬該等級。此為典型不等值連接 (BETWEEN)。
SELECT e.empno, e.ename, e.sal, s.grade, d.dname
FROM emp e
JOIN dept d ON e.deptno = d.deptno
JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal;
同一張表在查詢中出現兩次 (或多次),視為不同別名,**將自身表的一個鏡像當作另一張表**,用於解決**同表內部關聯**問題 (如員工-主管、節點-父節點、帳戶-轉帳對手)。
SELECT w.ename AS employee, w.mgr AS mgr_empno, m.ename AS manager
FROM emp w
JOIN emp m ON w.mgr = m.empno;
w (Worker) 代表員工m (Manager) 代表主管 (同表不同別名)| EMPLOYEE | MGR_EMPNO | MANAGER |
|---|---|---|
| SMITH | 7902 | FORD |
| ALLEN | 7698 | BLAKE |
| KING | (NULL) | (NULL) |
KING 為社長無主管,MGR 為 NULL,若需保留 KING 列需改用 LEFT JOIN。
SELECT w.ename AS employee, m.ename AS manager
FROM emp w
LEFT JOIN emp m ON w.mgr = m.empno;
SELECT LPAD(' ', 2*(LEVEL-1)) || ename AS org_chart, LEVEL
FROM emp
START WITH mgr IS NULL
CONNECT BY PRIOR empno = mgr;
此為遞歸查詢,非單純自我連接,但本質相同:表自我關聯形成樹狀結構。
| 場景 | 建議 |
|---|---|
| 不等值連接大表 | 確保連接欄位有索引;考慮將區間表 (如 SALGRADE) 設為小表驅動大表 (HASH JOIN) |
| 自我連接大表 | 關聯欄位 (如 MGR, EMPNO) 必須有索引;若頻繁查詢組織架構,考慮 Materialized View 預計算 |
| 複雜多表混合 | 使用 CTE 拆解邏輯,逐步 JOIN;善用 /*+ LEADING */ /*+ USE_HASH */ Hint 引導優化器 |