【问题标题】:SQL Query / Herigate data joinSQL 查询/继承数据连接
【发布时间】:2013-09-04 12:20:18
【问题描述】:

我有两个表,第一个是人员数据

ID
Name

第二个有每个人的亲人

Primary Key Field
Person (references person.id)
RelativeType (mother or father)
Parent (references person.id)

我正在尝试获取特定人员的所有儿子和孙子,但我无法将孙子整合到查询结果中。我正在使用 SQL Server。

有什么想法吗?

【问题讨论】:

  • 这是使用公用表表达式 (CTE) 的好场景。你可以在 StackOverflow 上找到很多例子
  • 您没有指定性别的字段。你是指子孙吗?
  • 我编辑了原始问题,因此母亲或父亲不再相关。我只需要到孙子的整个继承树
  • 这将向您展示如何进行递归 CTE:stackoverflow.com/questions/11636420/a-real-recursion-with-cte

标签: sql sql-server


【解决方案1】:

您需要的查询很大程度上取决于您的父子关系的级别。如果您可以更改架构,我建议您转而使用HierarchyId,这是一种 SQL Server 特定的数据类型。看看here

在下文中,我假设您只有 2 个级别。父亲-儿子-孙子

;WITH Sons AS (
    SELECT pdf.Id, pdf.Name, pdd.Id ParentId, pdd.Name Parent FROM PersonData pdf
    JOIN PersonRelative pr ON pdf.Id = pr.Parent
    JOIN PersonData pdd ON pr.Person = pdd.Id //Selecting all Parents
)

SELECT pd.Name, s.Name Son, 'Son' Type FROM PersonData pd
JOIN Sons s on pd.Id = s.ParentId

UNION

SELECT pd.Name, gs.Name Son, 'GrandSon' Type FROM PersonData pd
JOIN Sons s on pd.Id = s.ParentId
JOIN Sons gs on s.Id = gs.ParentId

【讨论】:

    【解决方案2】:

    试试这样的东西(未经测试):

    declare @person bigint = 123
    ;with cte as
    (
        select p.id, p.name, r.relativetype, r.parent, 0 decendantLevel 
        from  person p
        inner join relatives r
        on p.id = r.person
        where p.id = @person --select the ancestor who's tree we're interested in (if we don't want to include the person themselves change p.id to r.parent)
    
        union all
    
        select p.id, p.name, r.relativetype, r.parent, c.decendantLevel + 1
        from  person p
        inner join relatives r
        on p.id = r.person
        inner join cte c
        on c.id = r.parentid
    )
    select * from cte order by decendantLevel 
    

    【讨论】:

      【解决方案3】:

      就像提到的recursive CTE 是实现这一目标的方法:

      DECLARE @PersonToFind INT
      SET @PersonToFind = 1
      
      ;WITH RCTE AS 
      (
          SELECT Person, CAST('Child' AS NVARCHAR(MAX)) AS Relation 
          FROM PersonRelations 
          WHERE Father = @PersonToFind OR Mother = @PersonToFind 
      
          UNION ALL
      
          SELECT pr.Person, 'Grand' + r.Relation
          FROM PersonRelations pr 
              INNER JOIN RCTE r ON r.Person = pr.Mother OR r.Person = pr.Father
      )
      SELECT r.*, p.Name 
      FROM RCTE r
          LEFT JOIN Person p ON r.Person = p.ID
      

      SQLFiddle DEMO

      (这是在编辑问题之前使用母亲和父亲列,所以只需更改为 Parent,其中有 Mother OR Father 支票)

      【讨论】:

        【解决方案4】:

        感谢所有答案,CTE 是要走的路。我从每个答案中提取部分并以此结束

        with Sons as (select P1.Person as PersonSon from Persons 
        join relatives as P1 on P1.Parent = Persons.Id
        where Persons.Name = 'Mary') 
        
        select Id from Persons 
        join (
        select P2.Person as PersonSon from Relatives as P2
        join Sons on P2.Parent = Sons.PersonSon ) as P3 on Persons.Id = P3.PersonSon
        union all select Sons.PersonSon from Sons
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-04-27
          • 1970-01-01
          • 2021-10-07
          • 1970-01-01
          • 1970-01-01
          • 2014-03-01
          • 1970-01-01
          相关资源
          最近更新 更多