我在表“ 示例* ” 中有一个列名称“ 父级” 和“ 子级” ,以下是表数据 *
| Parent | Child |
|---------------------|------------------|
| 100 | 101 |
|---------------------|------------------|
| 101 | 102 |
|---------------------|------------------|
| 200 | 201 |
|---------------------|------------------|
| 103 | 102 |
|---------------------|------------------|
| 202 | 201 |
|---------------------|------------------|
如果我将输入设为 100,那么 我应该得到的结果为 100,101,102,103。 由于 100- > 101-> 102->
103
,而且如果我将输入设为 102, 则它也将得到与上述相同的结果。 102- > 101-> 100和102->
103
。我只需要使用存储过程来实现此目的。
以下是我正在尝试的示例代码
CREATE PROCEDURE GetAncestors(@thingID varchar(MAX))
AS
BEGIN
SET NOCOUNT ON;
WITH
CTE
AS
(
SELECT
Example.Parent, Example.Child
FROM Example
WHERE Parent = @thingID or Child = @thingID
UNION ALL
SELECT
Example.Parent, Example.Child
FROM
CTE
INNER JOIN Example ON Example.Parent = CTE.Child
)
SELECT
Parent AS Result
FROM CTE
UNION
SELECT
Child AS Result
FROM CTE
;
END
GO
您尝试的问题是在一开始就进行过滤。如果我是对的,则您希望按数据的升序或后代关系,或它们的混合关系对数据进行聚类(将所有数据分组在一起)。例如,ID100
具有child
101
,具有另一个child 102
,但是102
具有父级,103
并且您希望该100, 101, 102, 103
集合中任何输入的结果均为这四个()。这就是为什么您不能一开始就进行过滤的原因,因为您没有任何方法可以知道哪个关系将在另一个关系中链接在一起。
解决这个问题并不像看起来那么简单,并且您将无法仅通过1次递归来解决它。
以下是我很久以前就将所有这些关系分组在一起的解决方案。请记住,对于大型数据集(超过10万个),可能要花一些时间进行计算,因为它必须首先识别所有组,然后最后选择结果。
CREATE PROCEDURE GetAncestors(@thingID INT)
AS
BEGIN
SET NOCOUNT ON
-- Load your data
IF OBJECT_ID('tempdb..#TreeRelationship') IS NOT NULL
DROP TABLE #TreeRelationship
CREATE TABLE #TreeRelationship (
RelationID INT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED,
Parent INT,
Child INT,
GroupID INT)
INSERT INTO #TreeRelationship (
Parent,
Child)
SELECT
Parent = D.Parent,
Child = D.Child
FROM
Example AS D
UNION -- Data has to be loaded in both ways (direct and reverse) for algorithm to work correctly
SELECT
Parent = D.Child,
Child = D.Parent
FROM
Example AS D
-- Start algorithm
IF OBJECT_ID('tempdb..#FirstWork') IS NOT NULL
DROP TABLE #FirstWork
CREATE TABLE #FirstWork (
Parent INT,
Child INT,
ComponentID INT)
CREATE CLUSTERED INDEX CI_FirstWork ON #FirstWork (Parent, Child)
INSERT INTO #FirstWork (
Parent,
Child,
ComponentID)
SELECT DISTINCT
Parent = T.Parent,
Child = T.Child,
ComponentID = ROW_NUMBER() OVER (ORDER BY T.Parent, T.Child)
FROM
#TreeRelationship AS T
IF OBJECT_ID('tempdb..#SecondWork') IS NOT NULL
DROP TABLE #SecondWork
CREATE TABLE #SecondWork (
Component1 INT,
Component2 INT)
CREATE CLUSTERED INDEX CI_SecondWork ON #SecondWork (Component1)
DECLARE @v_CurrentDepthLevel INT = 0
WHILE @v_CurrentDepthLevel < 100 -- Relationships depth level can be controlled with this value
BEGIN
SET @v_CurrentDepthLevel = @v_CurrentDepthLevel + 1
TRUNCATE TABLE #SecondWork
INSERT INTO #SecondWork (
Component1,
Component2)
SELECT DISTINCT
Component1 = t1.ComponentID,
Component2 = t2.ComponentID
FROM
#FirstWork t1
INNER JOIN #FirstWork t2 on
t1.child = t2.parent OR
t1.parent = t2.parent
WHERE
t1.ComponentID <> t2.ComponentID
IF (SELECT COUNT(*) FROM #SecondWork) = 0
BREAK
UPDATE #FirstWork SET
ComponentID = CASE WHEN items.ComponentID < target THEN items.ComponentID ELSE target END
FROM
#FirstWork items
INNER JOIN (
SELECT
Source = Component1,
Target = MIN(Component2)
FROM
#SecondWork
GROUP BY
Component1
) new_components on new_components.source = ComponentID
UPDATE #FirstWork SET
ComponentID = target
FROM #FirstWork items
INNER JOIN(
SELECT
source = component1,
target = MIN(component2)
FROM
#SecondWork
GROUP BY
component1
) new_components ON new_components.source = ComponentID
END
;WITH Groupings AS
(
SELECT
parent,
child,
group_id = DENSE_RANK() OVER (ORDER BY ComponentID DESC)
FROM
#FirstWork
)
UPDATE FG SET
GroupID = IT.group_id
FROM
#TreeRelationship FG
INNER JOIN Groupings IT ON
IT.parent = FG.parent AND
IT.child = FG.child
-- Select the proper result
;WITH IdentifiedGroup AS
(
SELECT TOP 1
T.GroupID
FROM
#TreeRelationship AS T
WHERE
T.Parent = @thingID
)
SELECT DISTINCT
Result = T.Parent
FROM
#TreeRelationship AS T
INNER JOIN IdentifiedGroup AS I ON T.GroupID = I.GroupID
END
你会看到,@thingID
价值100
,101
,102
和103
结果是这四个,和值200
,201
并且202
结果是这三种。
我很确定这不是一个最佳解决方案,但是它可以提供正确的输出,而且我不需要对其进行调整,因为它可以快速满足我的要求。
问题内容: 我有一个“班级”,称为: 对于我的项目而言,它们所涉及的所有枚举都非常重要(因为这是类的构造函数中的一个参数)。 我如何使用层次结构/嵌套来实现以下目的: 一种测试an 是否属于A,B或C组的方法。例如,类似于或将是返回true的公共方法。 能够做同样的事情组的子组,和。例如,A组可能有子组,和。然后,我想要一个做某事的方法,例如which 。 一种无需所有复杂名称即可完成所有代码的方
问题内容: 我有代表文件夹的对象,我想知道是否应该在数据库中代表它们。 一方面,似乎最简单的方法是不表示文件夹对象,而只存储文件夹中包含的对象的路径值。我看到的问题是,您不能保留其后代不包含任何项目的文件夹,这并不是一件大事。我也不清楚如何在不将所有内容预先加载到内存的情况下加载要显示的文件夹层次结构(例如在TreeView中),这可能是性能问题。 另一种方法是拥有一个“文件夹”表,该表引用其父文
问题内容: 假设您有以下HTML: 请注意,层次结构是平坦的。 现在尝试选择元素的“中间对” 。这可能吗?我真的不知道怎么做。 此选择器仅获取后面的第一个: 但是此选择器将获取正确的元素对 以及我们想要的对之后出现的所有以下元素: 可能吗? 没有JavaScript。 没有标记更改。通用解决方案。允许任意数量的s或s,在这种情况下,数量2是任意的。 我在想使用选择器使用某些方法是可能的,但我似乎无
5.4.1 层次化体系结构 层次化设计是构造复杂系统的一个基本方法,按此方法设计出的系统具有层次化体系结构。现实世界中这种层次化结构俯拾皆是。例如,一幢高楼总是从最底层打基础开始,一层 一层地加高。又如,我国的行政组织具有街道、区、市、省、中央这样的层次化结构。 计算机软件的各个构件也经常组织成这样的层次体系结构。在层次体系中,下层构件为 上层构件提供服务,上层构件使用下层构件的服务,上层和下层之
问题内容: 我刚刚用ViewController类创建了一个单视图应用程序项目。我想显示一个位于我自己的类中的函数的UIAlertController。 这是我的课程,带有警告。 这是执行警报的ViewController。 这是我得到的,而不是优美的警报。 警告:尝试在Sprint1.AlertController:0x797cc500上显示其视图不在窗口层次结构中的UIAlertControl
我正在为我的项目使用Spring Data JPA(以hibernate作为提供程序),并想知道何时需要实体之间的双向映射? 在我的用例中,我有一个实体,与实体具有关系。目前,我在实体中没有相应的关系。从我所能理解的查看其他帖子,除非我需要通过我的实体/Hibernate删除,否则我可能不需要这样做。我想知道通过双向关系我还能得到什么? 这是我的,不包括访问者: 这是,不包括访问器: 如果我一直在