创建Id'的包含列表;使用SQL从直接/间接关系中删除
我有以下一组直接和间接文档依赖关系(按类型): 我需要生成整个依赖项链的包含列表,而不管我是否是插件创建Id'的包含列表;使用SQL从直接/间接关系中删除,sql,sql-server,Sql,Sql Server,我有以下一组直接和间接文档依赖关系(按类型): 我需要生成整个依赖项链的包含列表,而不管我是否是插件 顶级文档ID或DependencyId 任何中间文档ID或DependencyId 底部的DocumentId或DependencyId 例如 如果我插入18…我应该得到18,16,20,22 如果我插入20或16…我应该得到18,16,20,22 如果我插入22…我应该得到18,16,20,22 保留在中间可能存在我不想包括的其他记录: 请参见下图中的白色行 我不确定发布我的代
- 顶级文档ID或DependencyId
- 任何中间文档ID或DependencyId
- 底部的DocumentId或DependencyId
- 如果我插入18…我应该得到18,16,20,22
- 如果我插入20或16…我应该得到18,16,20,22
- 如果我插入22…我应该得到18,16,20,22
- 请参见下图中的白色行
下面是本地设置的代码
/****** Object: Table [dbo].[Document] Script Date: 2/13/2018 9:15:57 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Document](
[Id] [int] NOT NULL,
[ParentId] [int] NULL,
CONSTRAINT [PK_dbo.Document] PRIMARY KEY CLUSTERED
(
[Id] 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
/****** Object: Table [dbo].[DocumentDependency] Script Date: 2/13/2018 9:15:57 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[DocumentDependency](
[DocumentId] [int] NOT NULL,
[DependencyId] [int] NOT NULL,
[DependencyTypeName] [varchar](100) NOT NULL,
CONSTRAINT [PK_dbo.DocumentDependency] PRIMARY KEY CLUSTERED
(
[DocumentId] ASC,
[DependencyId] ASC,
[DependencyTypeName] 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
SET ANSI_PADDING OFF
GO
INSERT [dbo].[Document] ([Id], [ParentId]) VALUES (1, NULL)
GO
INSERT [dbo].[Document] ([Id], [ParentId]) VALUES (2, 1)
GO
INSERT [dbo].[Document] ([Id], [ParentId]) VALUES (3, 2)
GO
INSERT [dbo].[Document] ([Id], [ParentId]) VALUES (4, NULL)
GO
INSERT [dbo].[Document] ([Id], [ParentId]) VALUES (5, 4)
GO
INSERT [dbo].[Document] ([Id], [ParentId]) VALUES (6, 5)
GO
INSERT [dbo].[Document] ([Id], [ParentId]) VALUES (7, 5)
GO
INSERT [dbo].[DocumentDependency] ([DocumentId], [DependencyId], [DependencyTypeName]) VALUES (2, 1, N'DeviceAffinity')
GO
INSERT [dbo].[DocumentDependency] ([DocumentId], [DependencyId], [DependencyTypeName]) VALUES (3, 1, N'DeviceAffinity')
GO
INSERT [dbo].[DocumentDependency] ([DocumentId], [DependencyId], [DependencyTypeName]) VALUES (5, 4, N'DeviceAffinity')
GO
INSERT [dbo].[DocumentDependency] ([DocumentId], [DependencyId], [DependencyTypeName]) VALUES (6, 4, N'DeviceAffinity')
GO
INSERT [dbo].[DocumentDependency] ([DocumentId], [DependencyId], [DependencyTypeName]) VALUES (7, 6, N'DeviceAffinity')
GO
ALTER TABLE [dbo].[Document] WITH CHECK ADD CONSTRAINT [FK_dbo.Document_dbo.Document_ParentId] FOREIGN KEY([ParentId])
REFERENCES [dbo].[Document] ([Id])
GO
ALTER TABLE [dbo].[Document] CHECK CONSTRAINT [FK_dbo.Document_dbo.Document_ParentId]
GO
ALTER TABLE [dbo].[DocumentDependency] WITH CHECK ADD CONSTRAINT [FK_DocumentDependency_Document] FOREIGN KEY([DocumentId])
REFERENCES [dbo].[Document] ([Id])
GO
ALTER TABLE [dbo].[DocumentDependency] CHECK CONSTRAINT [FK_DocumentDependency_Document]
GO
ALTER TABLE [dbo].[DocumentDependency] WITH CHECK ADD CONSTRAINT [FK_DocumentDependency_Document1] FOREIGN KEY([DependencyId])
REFERENCES [dbo].[Document] ([Id])
GO
ALTER TABLE [dbo].[DocumentDependency] CHECK CONSTRAINT [FK_DocumentDependency_Document1]
GO
首先,需要一个递归CTE来获取填充列表。这里有一种方法:
with cte as (
select t.documentId, t.dependencyId, t.documentId as top_id
from t
where dependencyId is null
union all
select t.documentId, t.dependencyId, cte.top_id
from cte join
t
on cte.dependencyId = t.documentId
)
select * from CTE
接下来,您可以查找所需的id:
with cte as (
select t.documentId, t.dependencyId, t.documentId as top_id
from t
where dependencyId is null
union all
select t.documentId, t.dependencyId, cte.top_id
from cte join
t
on cte.dependencyId = t.documentId
)
select *
from cte
where cte.top_id = (select cte2.top_id from cte cte2 where cte2.documentId = ?);
你可以用这个
DECLARE @Id INT = 7
;WITH CTE AS (
SELECT *, RN = ROW_NUMBER() OVER(ORDER BY DocumentId) FROM [DocumentDependency]
),
CTE1 AS (
SELECT *, RN AS RL FROM CTE
UNION ALL
SELECT T.*, CTE1.RL FROM CTE T
INNER JOIN CTE1 ON (CTE1.DependencyId IN ( T.DependencyId, T.DocumentId ) OR CTE1.DocumentId IN ( T.DependencyId, T.DocumentId ) )
AND T.RN > CTE1.RN
)
, CTE2 AS
(
SELECT * FROM CTE1 WHERE RL =
(SELECT MIN (RL) FROM CTE1 WHERE DependencyId = @Id or DocumentId = @Id)
)
SELECT DocumentId FROM CTE2
UNION
SELECT DependencyId FROM CTE2
@Id=7的结果:
DocumentId
-----------
4
5
6
7
@Id=2的返回结果:
DocumentId
-----------
1
2
3
很抱歉,但这不太有效……请澄清您的答案好吗?“不太有效”并不能真正帮助任何人理解正在发生的事情。对不起,上面的解决方案包括不应作为最终集一部分的记录。请看上面,谢谢,伙计……正如韦恩和加思曾经说过的,“我不配!我不配!”