使用SQL

时间:2018-02-13 13:10:06

标签: sql sql-server

我有以下一套直接&间接文档依赖关系(按类型):

enter image description here

无论是否插件,我都需要生成ENTIRE依赖关系链的包含列表。

  • TOP DocumentId或DependencyId
  • 任何MIDDLE DocumentId或DependencyId
  • BOTTOM DocumentId或DependencyId

例如

  • 如果我插入18 ......我应该得到18,16,20,22
  • 如果我插入20或16 ......我应该得到18,16,20,22
  • 如果我插入22 ......我应该得到18,16,20,22

保持中期其他记录可能存在,我不想包括:

  • 请参阅下面的图像白色行

enter image description here

我不确定发布我的代码是否有价值,因为它不起作用。但是,如果你想...我愿意。

SETUP:
以下是本地设置的代码...

/****** 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

2 个答案:

答案 0 :(得分:1)

首先,您需要一个递归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 = ?);

答案 1 :(得分:1)

您可以使用此

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