sql >> Database teknologi >  >> RDS >> Sqlserver

Find en forælder på øverste niveau i SQL

Du kan bruge rekursiv CTE til at opnå dette:

DECLARE @childID INT 
SET @childID  = 1 --chield to search

;WITH RCTE AS
(
    SELECT *, 1 AS Lvl FROM RelationHierarchy 
    WHERE ChildID = @childID

    UNION ALL

    SELECT rh.*, Lvl+1 AS Lvl FROM dbo.RelationHierarchy rh
    INNER JOIN RCTE rc ON rh.CHildId = rc.ParentId
)
SELECT TOP 1 id, Name
FROM RCTE r
inner JOIN dbo.Person p ON p.id = r.ParentId
ORDER BY lvl DESC
 

SQLFiddle DEMO

REDIGER - for opdateret anmodning til forældre på øverste niveau for alle børn:

;WITH RCTE AS ( SELECT ParentId, ChildId, 1 AS Lvl FROM RelationHierarchy UNION ALL SELECT rh.ParentId, rc.ChildId, Lvl+1 AS Lvl FROM dbo.RelationHierarchy rh INNER JOIN RCTE rc ON rh.ChildId = rc.ParentId ) ,CTE_RN AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY r.ChildID ORDER BY r.Lvl DESC) RN FROM RCTE r ) SELECT r.ChildId, pc.Name AS ChildName, r.ParentId, pp.Name AS ParentName FROM CTE_RN r INNER JOIN dbo.Person pp ON pp.id = r.ParentId INNER JOIN dbo.Person pc ON pc.id = r.ChildId WHERE RN =1

SQLFiddle DEMO

EDIT2 - for at få alle personer til at skifte JOINS lidt til sidst:

SELECT pc.Id AS ChildID, pc.Name AS ChildName, r.ParentId, pp.Name AS ParentName
FROM dbo.Person pc 
LEFT JOIN CTE_RN r ON pc.id = r.CHildId AND  RN =1
LEFT JOIN dbo.Person pp ON pp.id = r.ParentId
 

SQLFiddle DEMo



  1. ORA-06508:PL/SQL:kunne ikke finde den programenhed, der kaldes

  2. Sådan laver du en LEFT ANTI SEMI JOIN i SQL Server

  3. Returner en liste over tabeller fra en sammenkædet server i SQL Server (T-SQL-eksempler)

  4. MySQL COALESCE og NULLIF funktion