【问题标题】:SQL Loop over a family tree家谱上的 SQL 循环
【发布时间】:2010-05-11 12:46:18
【问题描述】:

使用 SQL Server 2008。 我有一个存储在表格中的动物家谱,并想提供一些关于后代“遗传多样性”(或不是)的信息。 在 SQL 中,我如何生成合理的指标来显示父母之间的密切关系? 也许某种百分比的共享血统,或者在有共同祖先之前可以追溯到几代?

AnimalTable 
Id
Name
mumId
dadId

select * from AnimalTable child
inner join AnimalTable mum on child.[mumId] = mum.[Id]
inner join AnimalTable dad on child.[dadId] = dad.[Id]

inner join AnimalTable mums_mum on mum.[mumId] = mums_mum.[Id]
inner join AnimalTable mums_dad on mum.[dadId] = mums_dad.[Id]

inner join AnimalTable dads_mum on dad.[mumId] = dads_mum.[Id]
inner join AnimalTable dads_dad on dad.[dadId] = dads_dad.[Id]

【问题讨论】:

  • 我在阅读“妈妈爸爸妈妈”时大笑。 :(
  • @Robin,没关系,如果你对所有其他令人担忧的排列都大笑。

标签: sql tsql family-tree


【解决方案1】:

我建议您使用 CTE(通用表表达式)查看递归。

这将允许您递归地查看父母,直到找到共同的祖先,同时保持其价值。

【讨论】:

    【解决方案2】:
    WITH    hier1(parent, level) AS
            (
            SELECT  mum, 1
            FROM    AnimalTable a
            WHERE   a.id = @first_animal
            UNION ALL
            SELECT  dad, 1
            FROM    AnimalTable a
            WHERE   a.id = @first_animal
            UNION ALL
            SELECT  mum, level + 1
            FROM    q
            JOIN    AnimalTable a
            ON      a.id = q.parent
            UNION ALL
            SELECT  dad, level + 1
            FROM    q
            JOIN    AnimalTable a
            ON      a.id = q.parent
            ),
            hier2(parent, level) AS
            (
            SELECT  mum, level
            FROM    AnimalTable a
            WHERE   a.id = @second_animal
            UNION ALL
            SELECT  dad, level
            FROM    AnimalTable a
            WHERE   a.id = @second_animal
            UNION ALL
            SELECT  mum, level + 1
            FROM    q
            JOIN    AnimalTable a
            ON      a.id = q.parent
            UNION ALL
            SELECT  dad, level + 1
            FROM    q
            JOIN    AnimalTable a
            ON      a.id = q.parent
            )
    SELECT  TOP 1
            h1.parent,
            CASE WHEN h1.level < h2.level THEN h1.level ELSE h2.level END AS minlevel
    FROM    hier1 h1
    JOIN    hier2 h2
    ON      h1.parent = h2.parent
    ORDER BY
            2
    

    【讨论】:

    • 谢谢,但我的代码有问题。我对 CTE 不熟悉。我在网上看到的所有示例都从根(总统)开始,然后沿着树向下工作。我想在另一个方向递归。 @first_animal、@second_animal 你设置了什么?'level' 是从哪里来的?
    • @simon:CTE 从@first_animal@second_animal(您要为其找到共同祖先的那些)开始,然后向上而不是向下。每个 CTE 返回所有祖先及其级别(1 用于父母,2 用于祖父母等)。然后查询只连接祖先并返回最近的一个(级别最低的那个)。
    【解决方案3】:

    这无法以现实的方式回答 - 暂时忽略 SQL 部分,但您甚至不知道自己想要什么。 “也许”——好吧,再想一想。如果你有多个部分祖先怎么办?那你怎么办?

    找到给定后代的所有祖先是微不足道的(临时表,递归填充它的父母,将“世代相隔”作为字段添加)。

    然后你可以加入两个临时表。到目前为止还不错(抱歉,基本上必须如此,因为您的层次结构可以追溯到很多代)。

    但是从那里你仍然必须找到一个真正合理的算法来说明这应该是什么意思 - 在非平凡的场景中;)

    【讨论】:

      猜你喜欢
      • 2018-07-31
      • 2023-03-24
      • 2012-12-25
      • 2022-12-16
      • 1970-01-01
      • 2017-05-16
      • 1970-01-01
      • 2016-03-17
      • 2016-11-06
      相关资源
      最近更新 更多