[sql]with..as表示式遞迴查詢
阿新 • • 發佈:2020-10-25
最近在工作中用到到了sql server的with..as,在此記錄下它的用法
WITH AS的含義
WITH AS短語,也叫做子查詢部分(subquery factoring)。查詢的結果集被稱為公用表表達式(CTE), 公用表表達式可以包括對自身的引用, 這種表示式稱為遞迴公用表表達式。
對於UNION ALL,使用WITH AS定義了一個UNION ALL語句,當該片斷被呼叫2次以上,優化器會自動將資料放入一個臨時表中,使用這種方式可以提高查詢速度。
WITH AS的用法
WITH AS的語法如下,還是比較簡單的
[ WITH <common_table_expression> [ ,...n ] ] <common_table_expression>::= expression_name [ ( column_name [ ,...n ] ) ] AS ( CTE_query_definition )
使用CTE的時候有幾點是需要注意的
- CTE後面必須直接跟使用它的SQL語句(如select、insert、update等)
- CTE後面也可以跟其他的CTE,但只能使用一個with,多個CTE中間用逗號(,)分隔
- CTE 可以引用自身,也可以引用在同一 WITH 子句中預先定義的 CTE。但不允許前向引用
使用WITH AS短語實現遞迴查詢
表定義
CREATE TABLE [dbo].[Menu] ( [Id] int NOT NULL, -- 主鍵,選單Id [Name] nvarchar(20) NOT NULL, -- 名稱 [ParentId] int DEFAULT(0) NOT NULL, -- 父級選單Id PRIMARY KEY CLUSTERED ([Id]) )
向上遞迴查詢
with temp as
(
select Id, Name, ParentId
from Menu
union all
select t.Id, t.Name, t.ParentId
from Menu t, temp where t.Id = temp.ParentId
)
select * from temp
向下遞迴查詢
with temp as ( select Id, Name, ParentId from Menu union all select t.Id, t.Name, t.ParentId from Menu t, temp where t.ParentId = temp.Id ) select * from temp
區別在於:t.Id = temp.ParentId和 t.ParentId = temp.Id 表示了不同的查詢方向
根據name進行模糊查詢,同時返回Leaf表示是否為葉子節點,以供前端渲染
with temp as
(
select Id, Name, ParentId
from Menu p where name like '%Key%'
union all
select t.Id, t.Name, t.ParentId
from Menu t, temp where t.Id = temp.ParentId
)
select distinct *,
CAST(ISNULL((select top 1 0 from Menu with(nolock) where Menu.ParentId = t1.Id), 1) AS bit) Leaf
from (
select distinct * from temp
) t1
order by Id