Recursive Query Using CTE in SQL Server
Dear Friends, here i am posting the replacement of cursors using recursive query with the use of CTE.
Table Creation Scripts : -
CREATE TABLE [dbo].[tb_mlm](
[ID] [int] IDENTITY(10000001,1) NOT NULL,
[User_ID] [int] NULL,
[PARENT_ID] [int] NULL,
[poss] [tinyint] NULL
) ON [PRIMARY]
GO
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(1,null,null)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(2,1,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(3,1,1)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(4,2,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(5,2,1)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(6,3,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(6,3,1)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(7,1,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(8,1,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(9,1,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(10,1,1)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(11,2,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(12,4,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(13,4,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(14,4,1)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(15,12,1)
CTE script to find out the left and the right count of any parent......
declare @PARENT_ID int = 1, @left int = 0, @right int = 1
;with CTE_REC([USER_ID], PARENT_ID) ---Calucation of Left Child
AS
(
select [USER_ID], PARENT_ID from tb_mlm where PARENT_ID = @PARENT_ID and poss = @left
UNION ALL
select tb_mlm.[USER_ID], tb_mlm.PARENT_ID from tb_mlm , CTE_REC where tb_mlm.PARENT_ID = CTE_REC.[USER_ID] --and poss = @left
),
CTE_REC_RIGHT([USER_ID], PARENT_ID) ---Calucation of Right Child
AS
(
select [USER_ID], PARENT_ID from tb_mlm where PARENT_ID = @PARENT_ID and poss = @right
UNION ALL
select tb_mlm.[USER_ID], tb_mlm.PARENT_ID from tb_mlm , CTE_REC_RIGHT where tb_mlm.PARENT_ID = CTE_REC_RIGHT.[USER_ID] --and poss = @right
),CTE_Left(Parent, count,ExactCount) ----Combining the result into 1 line for left calculation result
AS
(select @PARENT_ID as Parent , COUNT(CTE_REC.[USER_ID]) as count, (select COUNT(*) from CTE_REC where CTE_REC.PARENT_ID = @PARENT_ID) as 'ExactCount' from CTE_REC)
,CTE_Final(Parent, count,ExactCount) ----Combining the result into 1 line for right calculation result
AS
(select @PARENT_ID as Parent , COUNT(CTE_REC_RIGHT.[USER_ID]) as count, (select COUNT(*) from CTE_REC_RIGHT where CTE_REC_RIGHT.PARENT_ID = @PARENT_ID) as 'ExactCount' from CTE_REC_RIGHT)
SELECT CTE_Left.Parent, CTE_Left.count as 'TotalLeft' , CTE_Left.ExactCount as 'ExactLeftCount', CTE_Final.count as 'TotalRight' , CTE_Final.ExactCount as 'ExactRightCount'
from CTE_Left --Final Query that will contain the result
LEFT JOIN CTE_Final on(CTE_Final.Parent = CTE_Left.Parent)
Table Creation Scripts : -
CREATE TABLE [dbo].[tb_mlm](
[ID] [int] IDENTITY(10000001,1) NOT NULL,
[User_ID] [int] NULL,
[PARENT_ID] [int] NULL,
[poss] [tinyint] NULL
) ON [PRIMARY]
GO
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(1,null,null)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(2,1,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(3,1,1)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(4,2,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(5,2,1)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(6,3,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(6,3,1)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(7,1,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(8,1,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(9,1,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(10,1,1)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(11,2,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(12,4,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(13,4,0)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(14,4,1)
INSERT INTO [dbo].[tb_mlm]([User_ID] ,[PARENT_ID],[poss]) VALUES(15,12,1)
CTE script to find out the left and the right count of any parent......
declare @PARENT_ID int = 1, @left int = 0, @right int = 1
;with CTE_REC([USER_ID], PARENT_ID) ---Calucation of Left Child
AS
(
select [USER_ID], PARENT_ID from tb_mlm where PARENT_ID = @PARENT_ID and poss = @left
UNION ALL
select tb_mlm.[USER_ID], tb_mlm.PARENT_ID from tb_mlm , CTE_REC where tb_mlm.PARENT_ID = CTE_REC.[USER_ID] --and poss = @left
),
CTE_REC_RIGHT([USER_ID], PARENT_ID) ---Calucation of Right Child
AS
(
select [USER_ID], PARENT_ID from tb_mlm where PARENT_ID = @PARENT_ID and poss = @right
UNION ALL
select tb_mlm.[USER_ID], tb_mlm.PARENT_ID from tb_mlm , CTE_REC_RIGHT where tb_mlm.PARENT_ID = CTE_REC_RIGHT.[USER_ID] --and poss = @right
),CTE_Left(Parent, count,ExactCount) ----Combining the result into 1 line for left calculation result
AS
(select @PARENT_ID as Parent , COUNT(CTE_REC.[USER_ID]) as count, (select COUNT(*) from CTE_REC where CTE_REC.PARENT_ID = @PARENT_ID) as 'ExactCount' from CTE_REC)
,CTE_Final(Parent, count,ExactCount) ----Combining the result into 1 line for right calculation result
AS
(select @PARENT_ID as Parent , COUNT(CTE_REC_RIGHT.[USER_ID]) as count, (select COUNT(*) from CTE_REC_RIGHT where CTE_REC_RIGHT.PARENT_ID = @PARENT_ID) as 'ExactCount' from CTE_REC_RIGHT)
SELECT CTE_Left.Parent, CTE_Left.count as 'TotalLeft' , CTE_Left.ExactCount as 'ExactLeftCount', CTE_Final.count as 'TotalRight' , CTE_Final.ExactCount as 'ExactRightCount'
from CTE_Left --Final Query that will contain the result
LEFT JOIN CTE_Final on(CTE_Final.Parent = CTE_Left.Parent)
Comments
then check out the second query.
enjoy.