【问题标题】:self referencing table with child table带子表的自引用表
【发布时间】:2012-01-03 22:59:49
【问题描述】:

我有一个自引用表,内容如下:

Self-referencing parent table
ID  ParentID    Name
---------------------
1               John
2   1           Mike
3   2           Erin
4   1           Janie
5               Eric
6   5           Peter

树的层次结构应该是这样的

  • 约翰
    • 迈克
      • 艾琳
    • 珍妮
  • 埃里克
    • 彼得

还有一个存储父表叶子的子表,如下所示:

ID  Sales
3   100
3   100
4   200
4   200
6   300
6   300
6   300

我正在尝试将总和从叶节点向上汇总到层次结构,以便它返回为 ..

ID  Name    Sum
1   John    800
2   Mike    200
3   Erin    200
4   Janie   400
5   Eric    900
6   Peter   900

任何想法如何在 sql 2008 中实现这一点?提前致谢。

【问题讨论】:

    标签: sql sql-server-2008 tsql hierarchical-data


    【解决方案1】:

    编辑所有聚合移出 CTE

    WITH
      tree AS
    (
      SELECT
        id                AS root_id,
        name              AS root_name,
        id                AS leaf_id
      FROM
        yourTreeTable
    
      UNION ALL
    
      SELECT
        tree.root_id      AS root_id,
        tree.name         AS root_name,
        yourTreeTable.id  AS leaf_id
      FROM
        tree
      INNER JOIN
        yourTreeTable
          ON tree.leaf_id = yourTreeTable.ParentID
    )
    SELECT
      tree.root_id,
      tree.root_name,
      COALESCE(SUM(yourScoresTable.score), 0) AS total
    FROM
      tree
    LEFT JOIN
      yourScoresTable
        ON yourScoresTable.ID = tree.leafID
    GROUP BY
      tree.root_id,
      tree.root_name
    

    【讨论】:

    • 感谢您的回复,Dem。我在该查询中收到两条错误消息:GROUP BY, HAVING, or aggregate functions are not allowed in the recursive part of a recursive common table expression 'flattend'.Outer join is not allowed in the recursive part of a recursive common table expression 'flattend'. 。有什么想法吗?
    • @Eric - 我太缺乏实践了,我什至不记得会是这种情况。我已经重新编码,以便所有聚合都在 CTE 之外完成。
    • 抱歉回复晚了,我昨天早早离开了,我整个上午都在开会。查询就像魅力一样。但我无法理解 CTE 以及 COALESCE 函数的工作原理。我需要将 ParentID 列添加到结果中,以便我可以在应用程序中重建树结构,但我不断得到不同的计数。你能帮忙多一点吗?再次感谢。
    • 我通过加入树表来解决这个问题。非常感谢。
    【解决方案2】:

    这里是:

    让我们假设这个架构:

    ​create table #parent (
    ID int,
    ParentID int,
    Name varchar(50) );
    
    create table #child (
    ID int,
    Sales int );
    

    查询是自我解释的:

    WITH 
      tree AS
    (
      SELECT
        id as id_parent,
        id as id
      FROM
        #parent
      UNION ALL
      SELECT
        tree.id_parent as id_parent,
        #parent.id AS id
      FROM
        tree
      INNER JOIN
        #parent    
          ON tree.id = #parent.ParentID
    )
    SELECT
      #parent.id,
      #parent.name,
      COALESCE(SUM(#child.Sales), 0) AS total
    FROM
      #parent
    LEFT JOIN
      tree
        ON #parent.ID = tree.id_parent
    LEFT JOIN
      #child on tree.id = #child.id
    GROUP BY
      #parent.id,
      #parent.name
    

    CTE 返回每个员工 (#parent) 的“叶子”列表,然后查询此“叶子”的所有销售额的总和。 You can test it running.

    已编辑

    查询已修复。

    【讨论】:

    • 感谢您的回答。我试图运行查询,但我注意到根节点的总和不正确。约翰的总和应该是 800 而不是 400。
    • @Eric,已修复。但要小心,约翰的总和是 600 而不是 800 ( jhon = 0, Mike= 0 ,Erin= 100+100,Janie=200+200 )
    • 我的错。感谢您的纠正。我在这个问题上花了太多时间,我终于得到了我需要的东西。再次感谢。
    • 我之前已经检查过 Dems 的答案,因为他首先回答了这个问题,而且他的方法非常接近您给出的解决方案。如果我没有以正确的方式这样做,请告诉我。非常感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 2022-01-09
    • 1970-01-01
    • 2018-09-23
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    相关资源
    最近更新 更多