WITH common table expression works in Microsoft SQL Server?WITH common table expression works in Microsoft SQL Server. I saw an example in the SQL Cookbook, but don't quite understand it. Can one of you SQL gurus break it down a bit for me?emp table:
deptno ename
------ --------
10 CLARK
10 KING
10 MILLER
20 FORD
20 ADAMS
30 MARTIN
30 BLAKE
30 ALLEN
The WITH common table expression:
with x (deptno, cnt, names, empno, len) as
(
select deptno, count(*) over (partition by deptno),
cast(ename as varchar(100)),
empno, 1
from emp
union all
select x.deptno, x.cnt,
cast(x.names + ',' + e.ename as varchar(100)),
e.empno, x.len+1
from emp e, x
where e.deptno = x.deptno and e.empno > x.empno
)
select deptno, names
from x
where len = cnt
order by 1
The results:
deptno names
------ ----------------------
10 CLARK, KING, MILLER
20 FORD, ADAMS
30 MARTIN, BLAKE, ALLEN
select
deptno,
count(*) over (partition by deptno) AS cnt,
cast(ename as varchar(100)) AS names,
empno,
1 AS len
from emp
I've added some column aliases to make it clear what is happening. The only part you might get confused by here is the "count(*) over (partition by deptno)". This is called a "window clause/function", and it's basically a more powerful, generic "group by".deptno cnt names empno len
------ --- -------- ----- ---
10 3 CLARK 1 1*
10 3 KING 2 1*
10 3 MILLER 3 1*
20 2 FORD 4 1*
20 2 ADAMS 5 1*
30 3 MARTIN 6 1*
30 3 BLAKE 7 1*
30 3 ALLEN 8 1*
Keep in mind that I'm actually showing you two tables here! Now, the recursive term:select
x.deptno,
x.cnt,
cast(x.names + ',' + e.ename as varchar(100)) AS names,
e.empno,
x.len+1 AS len
from emp e, x
where
e.deptno = x.deptno and
e.empno > x.empno
The recursive term operates on your working table, and stores its results in an intermediate table. Then, after each pass the intermediate table (1) gets appended to the results table, and (2) replaces the working table.deptno cnt names empno len
------ --- -------------- ----- ---
10 3 CLARK 1 1
10 3 KING 2 1
10 3 MILLER 3 1
20 2 FORD 4 1
20 2 ADAMS 5 1
30 3 MARTIN 6 1
30 3 BLAKE 7 1
30 3 ALLEN 8 1
10 3 CLARK, KING 2 2*
10 3 CLARK, MILLER 3 2*
10 3 KING, MILLER 3 2*
20 2 FORD, ADAMS 5 2*
30 3 MARTIN, BLAKE 7 2*
30 3 MARTIN, ALLEN 8 2*
30 3 BLAKE, ALLEN 8 2*
Now, for the second pass, CROSS JOIN the working table (rows with asterisks) with the "emp" table gives:deptno cnt names empno len
------ --- ---------------------- ----- ---
10 3 CLARK 1 1
10 3 KING 2 1
10 3 MILLER 3 1
20 2 FORD 4 1
20 2 ADAMS 5 1
30 3 MARTIN 6 1
30 3 BLAKE 7 1
30 3 ALLEN 8 1
10 3 CLARK, KING 2 2
10 3 CLARK, MILLER 3 2
10 3 KING, MILLER 3 2
20 2 FORD, ADAMS 5 2
30 3 MARTIN, BLAKE 7 2
30 3 MARTIN, ALLEN 8 2
30 3 BLAKE, ALLEN 8 2
10 3 CLARK, KING, MILLER 3 3*
30 3 MARTIN, BLAKE, ALLEN 8 3*
select deptno, names from x where len = cnt order by 1Basically, return the rows that contain the same number of names as we determined were in the department.
You are not logged in, either login or create an account to post comments
"with x (deptno, cnt, names, empno, len)..." says to create a temporary table called "x", with the 5 column names shown in the brackets.
"... as ( big complicated query in here )" says that the temporary table will be filled by the results of the big complicated query.
Then in the immediately following select statement, you use x as though it was a real table. In fact it isn't, and it will disappear by itself as soon as this query finishes, but for the purposes of that one query, x works just like a table.
The example in your question is very good for obscuring the key point about what a common table expression is, so if this is the example they used to illustrate the concept in the book, they should be shot.
posted by FishBike at 3:38 PM on September 11