程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> 其他數據庫知識 >> MSSQL >> Sql進修第三天——SQL 關於CTE(公用表達式)的遞歸查詢應用

Sql進修第三天——SQL 關於CTE(公用表達式)的遞歸查詢應用

編輯:MSSQL

Sql進修第三天——SQL 關於CTE(公用表達式)的遞歸查詢應用。本站提示廣大學習愛好者:(Sql進修第三天——SQL 關於CTE(公用表達式)的遞歸查詢應用)文章只能為提供參考,不一定能成為您想要的結果。以下是Sql進修第三天——SQL 關於CTE(公用表達式)的遞歸查詢應用正文


關於應用CTE(公用表表達式)的遞歸查詢----SQL Server 2005及以上版本

  公用表表達式 (CTE) 具有一個主要的長處,那就是可以或許援用其本身,從而創立遞歸 CTE。遞歸 CTE 是一個反復履行初始 CTE 以前往數據子集直到獲得完全成果集的公用表表達式。

  當某個查詢援用遞歸 CTE 時,它即被稱為遞歸查詢。遞歸查詢平日用於前往分層數據,例如:顯示某個組織圖中的雇員或物料清雙方案(個中父級產物有一個或多個組件,而那些組件能夠還有子組件,或許是其他父級產物的組件)中的數據。

  遞歸 CTE 可以極年夜地簡化在 SELECT、INSERT、UPDATE、DELETE 或 CREATE VIEW 語句中運轉遞歸查詢所需的代碼。在 SQL Server 的晚期版本中,遞歸查詢平日須要應用暫時表、游標和邏輯來掌握遞歸步調流。 

CTE 的根本語法構造以下:

    WITH expression_name [ ( column_name [,...n] ) ]

    AS

    ( CTE_query_definition )

    --只要在查詢界說中為一切成果列都供給了分歧的稱號時,列稱號列表才是可選的。

    --運轉 CTE 的語句為:

    SELECT <column_list> FROM expression_name;

在應用CTE時應留意以下幾點:

CTE前面必需直接跟應用CTE的SQL語句(如select、insert、update等),不然,CTE將掉效。以下面的SQL語句將沒法正常應用CTE:

  with
  cr as
  (
  select * from 表名 where 前提
   )
  --select * from person.CountryRegion --假如加上這句話前面用到cr將報錯
  select * from cr

2. CTE前面也能夠跟其他的CTE,但只能應用一個with,多個CTE中央用逗號(,)分隔,以下面的SQL語句所示:

with
cte1 as
(
select * from table1 where name like '測試%'
),
cte2 as
(
select * from table2 where id > 20
),
cte3 as
(
select * from table3 where price < 100
)
select a.* from cte1 a, cte2 b, cte3 c where a.id = b.id and a.id = c.id

3. 假如CTE的表達式稱號與某個數據表或視圖重名,則緊跟在該CTE前面的SQL語句應用的依然是CTE,固然,前面的SQL語句應用的就是數據表或視圖。

4. CTE 可以援用本身,也能夠援用在統一 WITH 子句中事後界說的 CTE。

5. 不克不及在 CTE_query_definition 中應用以下子句:

COMPUTE 或 COMPUTE BY
ORDER BY(除非指定了 TOP 子句)
INTO
帶有查詢提醒的 OPTION 子句
FOR XML
FOR BROWSE

6. 假如將 CTE 用在屬於批處置的一部門的語句中,那末在它之前的語句必需以分號開頭,以下面的SQL所示:

declare @s nvarchar(3)
set @s = '測試%'; -- 必需加分號
with
t_tree as
(
select * from 表 where 字段 like @s
)
select * from t_tree

------------------------------------操作------------------------------------

下面能夠對with as說的有點兒煩瑣了,上面進入正題:

老例子先建表(Co_ItemNameSet):

CREATE TABLE [dbo].[Co_ItemNameSet](
[ItemId] [int] NULL,
[ParentItemId] [int] NULL,
[ItemName] [nchar](10) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]

拔出數據:

--給表拔出數據
insert into dbo.Co_ItemNameSet values(2,0,'治理費用')
insert into dbo.Co_ItemNameSet values(3,0,'發賣費用')
insert into dbo.Co_ItemNameSet values(4,0,'財政費用')
insert into dbo.Co_ItemNameSet values(5,0,'臨盆本錢')
insert into dbo.Co_ItemNameSet values(35,5,'資料')
insert into dbo.Co_ItemNameSet values(36,5,'人工')
insert into dbo.Co_ItemNameSet values(37,5,'制作費用')
insert into dbo.Co_ItemNameSet values(38,35,'原資料')
insert into dbo.Co_ItemNameSet values(39,35,'重要資料')
insert into dbo.Co_ItemNameSet values(40,35,'間輔資料')
insert into dbo.Co_ItemNameSet values(41,36,'工資')
insert into dbo.Co_ItemNameSet values(42,36,'福利')
insert into dbo.Co_ItemNameSet values(43,2,'治理費用子項')
insert into dbo.Co_ItemNameSet values(113,43,'治理費用子項的子項')

查詢拔出的數據:

--查詢數據
select * from Co_ItemNameSet

成果圖:

標題需求是:查詢ItemId=2及子節點,也就是治理費用和其部屬一切節點的信息

操作1:先看看不消CTE遞歸操作的sql語句以下(須要真是的建兩個表停止數據的寄存和斷定,異常費事):

declare @i int
select @i=2;

create table #tem(
[ItemId] [INT] NOT NULL,
[level] INT
);

create table #list(
[ItemId] [INT] NOT NULL,
[ParentItemId] [INT] NOT NULL default ((0)),
[ItemName] [nvarchar](100) NOT NULL default (''),
[level] int
);

insert INTO #tem([ItemId],[level])
select ItemId,1
from Co_ItemNameSet
where itemid=@i

insert into #list([ItemId],[ParentItemId],[ItemName],[level])
select ItemId,ParentItemId,ItemName,1
from Co_ItemNameSet
where itemid=@i

declare @level int
select @level=1
declare @current INT
select @current=0

while(@level>0)
begin
select @current=ItemId
from #tem
where [level]=@level
if @@ROWCOUNT>0
begin


delete from #tem
where [level]=@level and ItemId=@current

insert into #tem([ItemId],[level])
select [ItemId],@level+1
from Co_ItemNameSet
where ParentItemId=@current

insert into #list([ItemId],[ParentItemId],[ItemName],[level])
select [ItemId],[ParentItemId],[ItemName],@level+1
from Co_ItemNameSet
where ParentItemId=@current
if @@rowcount>0
begin
select @level=@level+1
end
end
else
begin
select @level=@level-1
end
end

select * from #list
drop table #tem
drop table #list

成果圖:

操作2:用CTE遞歸操作的sql語句以下:

DECLARE @i INT
SELECT @i=2;
WITH Co_ItemNameSet_CTE(ItemId,ParentItemId,ItemName,[Level])
AS
(
SELECT ItemId,ParentItemId,ItemName,1 AS [Level]
FROM Co_ItemNameSet
WHERE itemid=@i
UNION ALL
SELECT c.ItemId,c.ParentItemId,c.ItemName,[Level] + 1
FROM Co_ItemNameSet c INNER JOIN Co_ItemNameSet_CTE ct
ON c.ParentItemId=ct.ItemId
)
SELECT * FROM Co_ItemNameSet_CTE

成果圖:

-----------------------------剖析(檢查MSDN的剖析)----------------------------

重要剖析一下用CTE的遞歸操作:

遞歸 CTE 由以下三個元素構成:

例程的挪用。

遞歸 CTE 的第一個挪用包含一個或多個由 UNION ALL、UNION、EXCEPT 或 INTERSECT 運算符聯接的 CTE_query_definitions。因為這些查詢界說構成了 CTE 構造的基准成果集,所以它們被稱為“定位點成員”。

CTE_query_definitions 被視為定位點成員,除非它們援用了 CTE 自己。一切定位點成員查詢界說必需放置在第一個遞歸成員界說之前,並且必需應用 UNION ALL 運算符聯接最初一個定位點成員和第一個遞歸成員。

例程的遞歸挪用。

遞歸挪用包含一個或多個由援用 CTE 自己的 UNION ALL 運算符聯接的 CTE_query_definitions(就是as裡的語句塊)。這些查詢界說被稱為“遞歸成員”。

終止檢討。

終止檢討是隱式的;當上一個挪用中未前往行時,遞歸將停滯。

    遞歸 CTE 構造必需至多包括一個定位點成員和一個遞歸成員。以下偽代碼顯示了包括一個定位點成員和一個遞歸成員的簡略遞歸 CTE 的組件。

    WITH cte_name ( column_name [,...n] )
    AS 
    (
    CTE_query_definition --定位點成員
    UNION ALL
    CTE_query_definition --遞歸成員. 
    )

    如今讓我們看一下遞歸履行進程:

    將 CTE 表達式拆分為定位點成員和遞歸成員。

    運轉定位點成員,創立第一個挪用或基准成果集 (T0)。

    運轉遞歸成員,將 Ti 作為輸出,將 Ti+1 作為輸入。

    反復步調 3,直到前往空集。

    前往成果集。這是對 T0 到 Tn 履行 UNION ALL 的成果。

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved