递归 CTE 查找父记录
首先我必须承认我对sql server的递归CTE 但我认为这是最好的方法。
我有一个表tabData
。它的 PK 名为 idData,并且有一个自引用 FK fiData。
因此 fiData 引用父记录,并且 SELECT * FROM tabData WHERE idData=fiData
返回所有数据父母的。这既简单又快速。但是如何按自然顺序从给定记录中获取所有父项呢? 假设有一个孩子(idData=4)和 3 个父母(第一个父母是 idData=3 的记录):
idData fiData
4 3
3 2
2 1
1 NULL
我认为递归 CTE 是可行的方法,但我不太适应它的语法。 那么实现返回所有父母的 CTE 的正确方法是什么?
我尝试了以下操作,但它给了我错误的结果(3,4而不是3,2,1): (为了测试它,我为我和你创建了一个临时表)
IF (NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'tabData_Temp'))
BEGIN
CREATE TABLE [dbo].[tabData_Temp](
[idData] [int] NOT NULL,
[fiData] [int] NULL,
CONSTRAINT [PK_tabData_Temp] PRIMARY KEY CLUSTERED
(
[idData] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
);
ALTER TABLE [dbo].[tabData_Temp] WITH CHECK ADD CONSTRAINT [FK_tabData_Temp] FOREIGN KEY([fiData])
REFERENCES [dbo].[tabData_Temp] ([idData]);
ALTER TABLE [dbo].[tabData_Temp] CHECK CONSTRAINT [FK_tabData_Temp];
INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(1,NULL);
INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(2,1);
INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(3,2);
INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(4,3);
END
/* here comes the (not working) recursive CTE */
Declare @fiData int;
SET @fiData = 3;
WITH PreviousClaims(idData,fiData)
AS(
SELECT parent.idData,parent.fiData
FROM tabData_temp parent
WHERE parent.idData = @fiData
UNION ALL
SELECT child.idData,child.fiData
FROM tabData_temp child
INNER JOIN PreviousClaims parent ON parent.idData = child.fiData
)
SELECT idData
FROM PreviousClaims;
/* end of recursive CTE */
DROP TABLE [dbo].[tabData_Temp];
提前谢谢您。
first i must admit that i'm not very familiar with sql server's recursive CTE's but i think this is the best approach.
I have a table tabData
. Its PK is named idData
and there is a self referencing FK fiData
.
So fiData references the parent record and SELECT * FROM tabData WHERE idData=fiData
returns all data of the parent. This is simple and fast. But how to get all parents from a given record in the natural order?
Say there is one child(idData=4) with 3 parents (first parent is the record with idData=3):
idData fiData
4 3
3 2
2 1
1 NULL
I thought recursive CTE is the way to go, but i don't get along well with its syntax.
So what is the correct way to implement the CTE which returns all parents?
I tried following, but it gives me the wrong result(3,4 instead of 3,2,1):
(To test it i created a temporary table for me and you)
IF (NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'tabData_Temp'))
BEGIN
CREATE TABLE [dbo].[tabData_Temp](
[idData] [int] NOT NULL,
[fiData] [int] NULL,
CONSTRAINT [PK_tabData_Temp] PRIMARY KEY CLUSTERED
(
[idData] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
);
ALTER TABLE [dbo].[tabData_Temp] WITH CHECK ADD CONSTRAINT [FK_tabData_Temp] FOREIGN KEY([fiData])
REFERENCES [dbo].[tabData_Temp] ([idData]);
ALTER TABLE [dbo].[tabData_Temp] CHECK CONSTRAINT [FK_tabData_Temp];
INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(1,NULL);
INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(2,1);
INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(3,2);
INSERT INTO [dbo].[tabData_Temp](idData,fiData)VALUES(4,3);
END
/* here comes the (not working) recursive CTE */
Declare @fiData int;
SET @fiData = 3;
WITH PreviousClaims(idData,fiData)
AS(
SELECT parent.idData,parent.fiData
FROM tabData_temp parent
WHERE parent.idData = @fiData
UNION ALL
SELECT child.idData,child.fiData
FROM tabData_temp child
INNER JOIN PreviousClaims parent ON parent.idData = child.fiData
)
SELECT idData
FROM PreviousClaims;
/* end of recursive CTE */
DROP TABLE [dbo].[tabData_Temp];
Thank you in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
更改为:
给了我你想要的结果。
Changing to:
Gave me the results you wanted.
你已经向后加入了。
把这个改成
这个
You have the join backward.
Change this
to this