SQL - 如何在自引用表中获取给定值的顶级父级

时间:2014-08-18 10:13:35

标签: sql sql-server

我有这个小问题。

该表基本上如下所示

主题

  • SubjectId
  • 主旨名称
  • ParentSubjectId

ParentSubjectId引用主题表本身。 它可以下降到很多级别(没有特定的级别数)

示例(仅为本示例使用国家/地区):

  1.Europe
  2.America
  1.1 France
  1.1 Italy
  2.1 USA
  2.2 Canada
  1.1.1 Paris
  1.2.1 Rome

依旧......

SubjectID是Guid ParentSubjectID也是一个GUID。

示例概述:http://i.imgur.com/a2u2CfT.png

它甚至可以无限期地下降(甚至可能达到街道数量级)

我的问题是: 给定一个主题(无论深度)。 我想获得该主题的顶级父母(在这种情况下为Europe/America

我该怎么做? 是否可以使用Basic SQL查询?

请注意我根本无法修改数据库(我从现有数据库中查询数据)

3 个答案:

答案 0 :(得分:1)

写为:

declare @Subject as varchar(max)
set @Subject = 'Rome'; -- set subject name here

WITH SubjectCTE AS
(
SELECT SubjectId , SubjectName , ParentSubjectId
FROM Subject
WHERE SubjectName = @Subject 
UNION ALL
SELECT C.SubjectId , C.SubjectName , C.ParentSubjectId
FROM SubjectCTE AS P
JOIN Subject AS C
ON P.ParentSubjectId = C.SubjectId
)
,SubjectCTE2 as 
(
SELECT SubjectId , SubjectName , ParentSubjectId, 
       Row_Number() over ( order by SubjectId asc) as rownum
FROM SubjectCTE
)
select SubjectName as RequiredParentName
from SubjectCTE2
where rownum =1 

check demo here..

答案 1 :(得分:0)

这很容易处理,只需添加新列HID(varchar)并填充它。

01     Europe
02     America
0101   France
0102   Italy
010101 Paris

选择父母:

DECLARE @childHID varchar(10) = '010101' --Paris

SELECT A.ID, A.Name
FROM Address A
WHERE A.HID = SUBSTRING(@childHID, 1, 2) -- first level

此外,您可以获得所有分支:

SELECT *
FROM Address
WHERE HID LIKE '01%'
ORDER BY HID

答案 2 :(得分:0)

对于它可能关心的人,我对@Mini的查询进行了一些改进,即使最顶层的父项链接到自身也会停止,即使一个孩子的父ID较小,它也会起作用:

declare @Subject as varchar(max)
set @Subject = 'Rome';

WITH SubjectCTE AS
(
    SELECT * FROM Subject
    WHERE SubjectName = @Subject
    UNION ALL
    SELECT C.*
    FROM SubjectCTE AS P
        JOIN Subject AS C
            ON P.ParentSubjectId = C.SubjectId 
    WHERE P.ParentSubjectId != P.SubjectId 
) SELECT SubjectName FROM SubjectCTE 
WHERE ParentSubjectId = SubjectId 
    OR ParentSubjectId IS NULL