1

我有一个我正在尝试解决的问题,我认为它与我在这里研究过的其他 SQL 邻接列表层次结构问题不同。我正在尝试对数据进行排序,以使所有孩子都列在他们的父母之前。我已经有返回给定 ParentID 的所有孩子和给定 ChildID 的所有父母的 CTE,但这些不符合我目前的需要。

我有两张桌子:

CREATE TABLE [dbo].[ItemMaster](
[ItemID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,

CREATE TABLE [dbo].[References](
[RefID] [int] IDENTITY(1,1) NOT NULL,
[ParentID] [int] NOT NULL,
[ChildID] [int] NOT NULL,

ItemMaster.ItemID 到 References.ParentID 和 References.ChildID 之间存在外键关系

这是我表中的一些示例数据...

物品 ID、名称

  • 1、A1
  • 2、A2
  • 3、A3
  • 4、P1
  • 5、P2
  • 6、P3
  • 7、P4
  • 8、TOP

RefID、ParentID、ChildID

  • 1,1,5
  • 2,2,5
  • 3,2,6
  • 4,3,2
  • 5,7,3
  • 6,8,4
  • 7,8,1
  • 8,8,2
  • 9,8,3
  • 10,8,7

我想要的输出将列出每个 ItemID 和 Name 以及在任何父母之前列出的孩子。像这样...

物品 ID、名称

  • 4、P1
  • 5、P2
  • 6、P3
  • 1、A1
  • 2、A2
  • 3、A3
  • 7、P4
  • 8、顶部

笔记:

  • 任何 ItemID 都可以有 0、1 或 > 1 个父项。
    • 那些没有任何父母的将列在输出的顶部。
  • 参考表中的“最重要的父母”没有 NULL 值。

我希望我已经提供了足够的细节并很好地解释了自己以获得一些反馈。任何想法将不胜感激!

4

1 回答 1

1

我认为实现这一点的方法是使用递归操作并根据其所有子节点的权重为每个节点分配权重。

例如,这棵树中的任何叶子的权重都为零,因为它没有任何子节点。它的直接父级将为 1,父级的父级为 2,依此类推。按重量排序应该返回您需要的结果集。这是我用来测试我的理论的递归函数:

CREATE FUNCTION [dbo].[GetItemWeight](@ItemID int)
RETURNS int
BEGIN

DECLARE @Weight int;

SELECT
  @Weight = COUNT(ParentID) 
FROM
  [References]
WHERE
  ChildID = @ItemID;

SELECT
  @Weight = ISNULL(@Weight, 0) + SUM(dbo.GetItemWeight(ChildID))
FROM
  [References]
WHERE
  ParentID = @ItemID;

RETURN ISNULL(@Weight, 0);
END

这将返回您发布的结果集:

SELECT ItemID, Name FROM ItemMaster ORDER BY dbo.GetItemWeight(ItemID);

祝你好运:)

于 2012-09-04T04:55:13.793 回答