【问题标题】:recursive sql, sql server 2012递归sql,sql server 2012
【发布时间】:2014-05-23 15:28:53
【问题描述】:

我正在尝试解决递归 SQL 问题,本质上是聚合一组记录的状态。

就问题而言 - 有两个表格。一种维护聚合/层次结构“GROUP_MEMBERS”,一种包含单个项目“ITEMS”。

“GROUP_MEMBERS”看起来很相似(ID 是 GROUPID,CHILDTYPE 是 0 表示组,1 表示单个项目,ID 是子项目 ID(因此类型 0 为 groupid,类型 1 为 itemid)

ID | CHILDTYPE | CHILDID

1       0        2
1       1        1
2       1        2
2       1        3
2       1        4

在这个例子中,我的“ITEMS”表只有两列:

ID | STATUS

1     0
2     1
3     0
4     0
5     0

实际上,我正在尝试做的是将所有“ITEMS”、ID 和 STATUS 递归地拉回一个组(因为组可以包含其他组)。因此,对于我提供的示例数据,如果我将 GROUPID 传递给 1,它将返回 ITEMS 1-4 及其状态; GROUPID 2 将是项目 2-4 及其状态等。

我假设我需要通过函数执行此操作并返回一个表,但我什至不确定从哪里开始。

【问题讨论】:

  • 您需要每组的项目(如表值函数)还是所有组的项目总列表?
  • 另外,您是否只有 1 级递归,或者可能更多?
  • 可能有超过 1 级的递归 - 我认为我更愿意通过 TVF 获得每组的项目。我想对返回的状态进行一些数学运算。

标签: sql sql-server-2012


【解决方案1】:

这是一个很好的谜题,一定要告诉你 :) 希望它是你想要的。

DECLARE @GroupRootID INT = 1
DECLARE @GROUP_MEMBERS TABLE (ID int, CHILDTYPE int, CHILDID int)
DECLARE @ITEMS TABLE (ID int, STATUS int)

INSERT INTO @GROUP_MEMBERS VALUES
(1,0,2), (1,1,1), (2,1,2), (2,0,3), (2,0,4), (2,1,3), (2,1,4), (3,1,5), (4,1,5)

INSERT INTO @ITEMS VALUES
(1,0), (2,1), (3,0), (4,0), (5,1)

--              1
--            /   \
--          2     items         items: 1 => 1,1,1
--        / |   \
--      3   4   items           items: 2,3,4 => 2,1,2 - 2,1,3 - 2,1,4
--      |   \   
--    items items               items (3): 5 => 3,1,5
--                              items (4); 5 => 4,1,5

/* Recursivly build the GROUP tree (groups that have subgroups, CHILDTYPE=0), but NOT the lead nodes (CHILDTYPE = 1) */
;WITH GROUP_TREE
AS
(
    /* SELECT all parents */
    SELECT ParentGroups.*, 0 AS LEVEL
    FROM @GROUP_MEMBERS AS ParentGroups
    WHERE ParentGroups.CHILDTYPE = 0
    AND ParentGroups.ID = @GroupRootID

    UNION ALL

    /* SELECT all childs groups for the parents */
    SELECT ChildGroups.*, LEVEL + 1
    FROM @GROUP_MEMBERS AS ChildGroups
    INNER JOIN GROUP_TREE AS Parent ON Parent.CHILDID = ChildGroups.ID
    WHERE ChildGroups.CHILDTYPE = 0
)

/* We now have all groups with their subgroups (not leaf nodes) */
/* Then join the leaf nodes (groups that are no subtree) */
/* Finally union the items from the root node and join the ITEMS to the leaf nodes to get the status */
/* Mind you though that ITEM 5 is linked double and will be returned NON-distinct */

SELECT ITEMS.*
FROM (
    SELECT GROUPS.*
    FROM @GROUP_MEMBERS AS GROUPS
    INNER JOIN GROUP_TREE ON GROUP_TREE.CHILDID = GROUPS.ID
    WHERE GROUPS.CHILDTYPE = 1

    UNION ALL

    SELECT GROUPS.*
    FROM @GROUP_MEMBERS AS GROUPS
    WHERE GROUPS.CHILDTYPE = 1
    AND GROUPS.ID = @GroupRootID
) AS GROUP_ITEMS
INNER JOIN @ITEMS AS ITEMS ON GROUP_ITEMS.CHILDID = ITEMS.ID

【讨论】:

  • +1 是我一段时间以来看到的最佳解释答案之一。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-19
  • 2011-01-10
  • 2017-02-02
  • 2012-12-05
  • 2013-07-25
相关资源
最近更新 更多