CREATE TABLE [dbo].[CategorySelf]( [PKID] [int] IDENTITY(1,1) NOT NULL, [C_Name] [nvarchar](50) NOT NULL, [C_Level] [int] NOT NULL, [C_Code] [nvarchar](255) NULL, [C_Parent] [int] NOT NULL, [InsertTime] [datetime] NOT NULL, [InsertUser] [nvarchar](50) NULL, [UpdateTime] [datetime] NOT NULL, [UpdateUser] [nvarchar](50) NULL, [SortLevel] [int] NOT NULL, [CurrState] [smallint] NOT NULL, [F1] [int] NOT NULL, [F2] [nvarchar](255) NULL CONSTRAINT [PK_OBJECTCATEGORYSELF] PRIMARY KEY CLUSTERED ( [PKID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO
再插入一些測試數據
INSERT INTO [CategorySelf]([C_Name],[C_Level] ,[C_Code],[C_Parent] ,[InsertTime] ,[InsertUser] ,[UpdateTime] ,[UpdateUser] ,[SortLevel] ,[CurrState] ,[F1] ,[F2]) select '分類1',1,'0',0,GETDATE(),'testUser',DATEADD(dd,1,getdate()),'CrackUser',13,0,1,'邀月備注' union all select '分類2',1,'0',0,GETDATE(),'testUser',DATEADD(dd,78,getdate()),'CrackUser',12,0,1,'邀月備注' union all select '分類3',1,'0',0,GETDATE(),'testUser',DATEADD(dd,6,getdate()),'CrackUser',10,0,1,'邀月備注' union all select '分類4',2,'1',1,GETDATE(),'testUser',DATEADD(dd,75,getdate()),'CrackUser',19,0,1,'邀月備注' union all select '分類5',2,'2',2,GETDATE(),'testUser',DATEADD(dd,3,getdate()),'CrackUser',17,0,1,'邀月備注' union all select '分類6',3,'1/4',4,GETDATE(),'testUser',DATEADD(dd,4,getdate()),'CrackUser',16,0,1,'邀月備注' union all select '分類7',3,'1/4',4,GETDATE(),'testUser',DATEADD(dd,5,getdate()),'CrackUser',4,0,1,'邀月備注' union all select '分類8',3,'2/5',5,GETDATE(),'testUser',DATEADD(dd,6,getdate()),'CrackUser',3,0,1,'邀月備注' union all select '分類9',4,'1/4/6',6,GETDATE(),'testUser',DATEADD(dd,7,getdate()),'CrackUser',5,0,1,'邀月備注' union all select '分類10',4,'1/4/6',6,GETDATE(),'testUser',DATEADD(dd,7,getdate()),'CrackUser',63,0,1,'邀月備注' union all select '分類11',4,'1/4/6',6,GETDATE(),'testUser',DATEADD(dd,8,getdate()),'CrackUser',83,0,1,'邀月備注' union all select '分類12',4,'2/5/8',8,GETDATE(),'testUser',DATEADD(dd,10,getdate()),'CrackUser',3,0,1,'邀月備注' union all select '分類13',4,'2/5/8',8,GETDATE(),'testUser',DATEADD(dd,15,getdate()),'CrackUser',1,0,1,'邀月備注' 一個典型的應用場景是:在這個自關聯的表中,查詢以PKID為2的分類包含所有子分類。也許很多情況下,我們不得不用臨時表/表變量/游標等。現在我們有了CTE,就簡單多了。
WITH SimpleRecursive(C_Name, PKID, C_Code,C_Parent) AS (SELECT C_Name, PKID, C_Code,C_Parent FROM CategorySelf WHERE PKID = 2 UNION ALL SELECT p.C_Name, p.PKID, p.C_Code,p.C_parent FROM CategorySelf P INNER JOIN SimpleRecursive A ON A.PKID = P.C_Parent ) SELECT sr.C_Name as C_Name, c.C_Name as C_ParentName,sr.C_Code as C_ParentCode FROM SimpleRecursive sr inner join CategorySelf c on sr.C_Parent=c.PKID
The statement terminated. The maximum recursion 1 has been exhausted before statement completion.
此時可以通過where條件來解決,而保證不出錯,看如下SQL語句:
WITH SimpleRecursive(C_Name, PKID, C_Code,C_Parent,Sublevel) AS (SELECT C_Name, PKID, C_Code,C_Parent,0 FROM CategorySelf WHERE PKID = 2 UNION ALL SELECT p.C_Name, p.PKID, p.C_Code,p.C_parent,Sublevel+1 FROM CategorySelf P INNER JOIN SimpleRecursive A ON A.PKID = P.C_Parent ) SELECT sr.C_Name as C_Name, c.C_Name as C_ParentName,sr.C_Code as C_ParentCode FROM SimpleRecursive sr inner join CategorySelf c on sr.C_Parent=c.PKID where SubLevel<=2
SELECT C_Name as C_Name, (Select top 1 C_Name from CategorySelf s where c.C_Parent=s.PKID) as C_ParentName,C_Code as C_ParentCode from CategorySelf c where C_Code like '2/%'
查詢以PKID為2的分類包含所有子分類,且級別不大于3。
SELECT C_Name as C_Name, (Select top 1 C_Name from CategorySelf s where c.C_Parent=s.PKID) as C_ParentName,C_Code as C_ParentCode from CategorySelf c where C_Code like '2/%' and C_Level<=3