在最近的活字格專案中使用activereports報表設計器設計乙個報表模板時,遇到乙個多級分類的難題:需要將某個部門所有銷售及下屬部門的銷售金額彙總,因為下屬級別的層次不確定,所以靠拼接子查詢的方式顯然是不能滿足要求,經過一番實驗,利用了cte(common table expression)很輕鬆解決了這個問題!
舉例:有如下的部門表
以及員工表
如果想查詢所有西北區的員工(包含西北、西安、蘭州),如下圖所示:
以下**使用sqlite 3.18.0 測試通過
with
[depts
]([dept_id
]) as
(
select[d
].[dept_id
]from
[dept][
d]join
[employees][
e]on[
d].[
dept_id]=
[e].[dept_id
]where[e
].[emp_name]=
'西北-經理
'union
allselect[d
].[dept_id
]from
[dept][
d]join
[depts][
s]on[
d].[
parent_id]=
[s].[dept_id])
select
*from
[employees
]where
[dept_id
]in (select
[dept_id
]from
[depts
]);我還是更喜歡稱cte(common table expression)為「公用表變數」而不是「公用表示式」,因為從行為和使用場景上講,cte更多的時候是產生(分迭代或者不迭代)結果集,供其後的語句使用(查詢、插入、刪除或更新),如上述的例子就是乙個典型的利用迭代遍歷樹形結構資料。
cte的優點:
為了更好的說明cte的能力,這裡附上兩個例子**自sqlite官網文件)
曼德勃羅集合(mandelbrot set)
--執行後的結果,如下圖:(使用sqlite expert personal 4.2 x64)以下**使用sqlite 3.18.0 測試通過
with
recursive
xaxis(x)
as (values(-
2.0) union
allselect x+
0.05
from xaxis where x<
1.2),
yaxis(y)
as (values(-
1.0) union
allselect y+
0.1from yaxis where y<
1.0),
m(iter, cx, cy, x, y) as(
select
0, x, y, 0.0, 0.0
from
xaxis, yaxis
union
allselect iter+
1, cx, cy, x*x-y*y + cx, 2.0
*x*y + cy from
m
where (x*x + y*y) <
4.0and iter<
28),
m2(iter, cx, cy) as(
select
max(iter), cx, cy from m group
bycx, cy
),a(t) as(
select group_concat( substr('
.+*#
', 1
+min(iter/
7,4), 1), ''
)
from m2 group
bycy
)select group_concat(rtrim(t),x'
0a') from a;
數獨問題(sudoku)
假設有類似下圖的問題:
以下**使用sqlite 3.18.0 測試通過
with
recursive
input(sud) as(
values('
53..7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79')
),digits(z, lp) as(
values('
1', 1
)
union
allselect
cast(lp+1as
text), lp+
1from digits where lp<9),
x(s, ind) as(
select sud, instr(sud, '
.') from
input
union
allselect
substr(s,
1, ind-
1) || z || substr(s, ind+1),
instr( substr(s,
1, ind-
1) || z || substr(s, ind+
1), '.'
)
from x, digits as
z
where ind>
0and
notexists
(
select
1from digits as
lp
where z.z = substr(s, ((ind-
1)/9)*
9+ lp, 1
)
or z.z = substr(s, ((ind-
1)%9) + (lp-
1)*9
+1, 1
)
or z.z = substr(s, (((ind-
1)/3) %
3) *
3+ ((ind-
1)/27) *27+
lp
+ ((lp-
1) /
3) *
6, 1
) )
)select s from x where ind=
0;執行結果(結果中的數字就是對應格仔中的答案)
附:sqlite中cte(with關鍵字)語法**:
cte是解決一些特定問題的利器,但了解和正確的使用是前提,在決定將已有的一些sql重構為cte之前,確保對已有語句有清晰的理解以及對cte足夠的學習!good luck~~~
附件:用到的sql指令碼
一句SQL完成動態分級查詢
在最近的 活字格專案中使用 activereports 報表設計器設計乙個報表模板時,遇到乙個多級分類的難題 需要將某個部門所有銷售及下屬部門的銷售金額彙總,因為下屬級別的層次不確定,所以靠拼接子查詢的方式顯然是不能滿足要求,經過一番實驗,利用了cte common table expression...
一句SQL完成動態分級查詢
如果想查詢所有西北區的員工 包含西北 西安 蘭州 如下圖所示 以下 使用sqlite 3.18.0 測試通過with depts dept id as select d dept id from dept d join employees e on d dept id e dept id where...
SQL 一句sql 分頁
有關分頁 sql 的資料很多,有的使用儲存過程,有的使用游標。本人不喜歡使用游標,我覺得它耗資 效率低 使用儲存過程是個不錯的選擇,因為儲存過程是經過預編譯的,執行效率高,也更靈活。先看看單條 sql 語句的分頁 sql 吧。方法1 適用於 sql server 2000 2005 select t...