當查詢很複雜,又需要反覆使用子查詢的結果時,WITH便很方便。如果想查出各部門中,哪一部門的總薪資,高於所有部門的平均薪資,那總平均薪資就屬於反覆使用的子查詢。透過WITH語法,將查詢語句包圍在一個WITH語句中,透過反覆呼叫該語句,便可以達成子查詢。
下面的 SQL 想查詢在每個部門裡有多少人,原來的SQL如下
SELECT e.first_name,e.last_name AS employee_name,
dc.department_id, dc.dept_count AS emp_dept_count
FROM emp e,
(SELECT department_id, COUNT(*) AS dept_count
FROM emp
GROUP BY department_id) dc
WHERE e.department_id = dc.department_id;
改用WITH語法後的SQL如下
WITH dept_count AS (
SELECT department_id, COUNT(*) AS dept_count
FROM emp
GROUP BY department_id)
SELECT e.first_name,e.last_name AS employee_name,
dc.department_id,dc.dept_count AS emp_dept_count
FROM emp e,
dept_count dc
WHERE e.department_id = dc.department_id;
從上面的語法,以WITH語法定義了一段子查詢,命名為 DEPT_COUNT,用在其後的SQL當中,如下圖所示。
要從本身具備階層關係的表格中,把部門員工和所屬主管及各部門人數拉出來,若用傳統SELF-JOIN的方式處理,其SQL如下:
SELECT e.last_name AS employee_name,
dc1.dept_count AS emp_dept_count,
m.last_name AS manager_name,
dc2.dept_count AS mgr_dept_count
FROM emp e,
(SELECT department_id, COUNT(*) AS dept_count
FROM emp
GROUP BY department_id) dc1,
emp m,
(SELECT department_id, COUNT(*) AS dept_count
FROM emp
GROUP BY department_id) dc2
WHERE e.department_id = dc1.department_id
AND e.manager_id = m.employee_id
AND m.department_id = dc2.department_id;
上述SQL的執行結果如下圖所示。 相同的查詢,若改以 WITH 的語法,看起來會較有結構。
WITH dept_count AS (
SELECT department_id, COUNT(*) AS dept_count
FROM emp
GROUP BY department_id)
SELECT e.last_name AS employee_name,
dc1.dept_count AS emp_dept_count,
m.last_name AS manager_name,
dc2.dept_count AS mgr_dept_count
FROM emp e,
dept_count dc1,
emp m,
dept_count dc2
WHERE e.department_id = dc1.department_id
AND e.manager_id = m.employee_id
AND m.department_id = dc2.department_id;
上述的語法可以結合兩種編譯註解 (HINTS) ,MATERIALIZE 使其以 global temporary table 的方式處理 WITH 的語句,INLINE 則是以內嵌的方式處理
WITH dept_count AS ( SELECT /*+ MATERIALIZE */ department_id, COUNT(*) AS dept_count FROM emp GROUP BY department_id) SELECT ............ ; WITH dept_count AS ( SELECT /*+ INLINE */ department_id, COUNT(*) AS dept_count FROM emp GROUP BY department_id) SELECT ..............;WITH 語法還可以讓重複使用的查詢,以代稱命名後,反覆呼叫使用。以下範例,透過 WITH 建立兩個子查詢,分別查詢部門總薪資(部門總成本或總薪資),及總平均薪資,簡化後的 SQL ,主體SQL變得非常簡潔。
WITH
dept_costs AS (
SELECT department_name, SUM(salary) dept_total
FROM emp e, departments d
WHERE e.department_id = d.department_id
GROUP BY department_name),
avg_cost AS (
SELECT SUM(dept_total)/COUNT(*) avg
FROM dept_costs)
SELECT *
FROM dept_costs
WHERE dept_total > (SELECT avg FROM avg_cost)
ORDER BY department_name;
上述查詢得到銷售部門總薪資高於全體平均薪資。



