The WITH clause, also known as the subquery factoring clause, was introduced in Oracle 9i as a way to make queries more efficient and readable. Let’s see how WITH works with a basic example.
Say we have three departments at our workplace – Accounting, Research and Sales – and we want to select only those departments with a total salary more than the average total.
The total salary per department is:
1
2
3
4
5
6
7
8
9
10
11
| SQL> select dname, sum(sal) as dept_total 2 from emp, dept 3 where emp.deptno = dept.deptno 4 group by dname 5 /DNAME DEPT_TOTAL-------------- ----------ACCOUNTING 9150RESEARCH 10875SALES 9400 |
The average total salary per department is:
1
2
3
4
5
6
7
8
| SQL> select sum(sal) * 1/3 2 from emp, dept 3 where emp.deptno = dept.deptno 4 /SUM(SAL)*1/3------------ 9808.33333 |
So the final query, without the WITH clause, will be:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| SQL> select dname, sum(sal) as dept_total 2 from emp, dept 3 where emp.deptno = dept.deptno 4 group by dname having 5 sum(sal) > 6 ( 7 select sum(sal) * 1/3 8 from emp, dept 9 where emp.deptno = dept.deptno 10 ) 11 order by sum(sal) desc;DNAME DEPT_TOTAL-------------- ----------RESEARCH 10875 |
Notice the problem? We’re duplicating a large part of the query, calculating the sum twice. This makes the query inefficient and poor to read.
That’s when the WITH clause comes to our rescue. When a subquery is being processed multiple times, WITH lets you factor it out, give it a name and then reference the name wherever needed in the query.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| SQL> with sumsal as 2 ( 3 select dname, sum(sal) as dept_total 4 from emp, dept 5 where emp.deptno = dept.deptno 6 group by dname 7 ) 8 -- End of factored subquery 9 -- Main query starts 10 select dname, dept_total 11 from sumsal -- Reference #1 12 where dept_total > 13 ( 14 select sum(dept_total) * 1/3 15 from sumsal -- Reference #2 16 ) 17 order by dept_total desc;DNAME DEPT_TOTAL-------------- ----------RESEARCH 10875 |
The rewritten query using WITH not just improves performance but also makes code easier to understand and maintain.
The WITH Clause Syntax
1
2
3
4
5
| with clause-name AS(subquery)main query referencing clause-name; |
The syntax of the WITH clause is analogous to defining a function and invoking it multiple times in the main program. There is one difference though, which we’ll look at in the next article: Why the SQL WITH clause is not exactly like a function definition.
No comments:
Post a Comment