查找自联接表的根父表用作外键的列

时间:2012-12-04 09:17:07

标签: sql sql-server-2008 tsql common-table-expression

我有一个Locations表,它是自行连接的,构成了行政区划的层次结构。与StateCountyTown等相同。 LocationId PK为此table的{​​{1}},Foreign key中的joining table使用ProjectId。加入表有LocationsIdroot-parent(State),项目可以在任何级别的位置,因此加入表可以有县,镇等。我想找出用作FK的位置sql。 请使用以下DECLARE @Locations TABLE (LocationId INT, LocationName VARCHAR(30), ParentId INT, LocLevel INT) INSERT INTO @Locations Values(1, 'State1', NULL, 1), (2, 'State1-County1', 1, 2), (3, 'State1-County1-Town1', 2, 3), (4, 'State1-County1-Town1-Muncip-1', 3, 4), (5, 'State1-County2', 1, 2), (6, 'State1-County2-Town1', 5, 3), (7, 'State1-County2-Town1-Muncip-1', 6, 4), (8, 'State2', NULL, 1), (9, 'State2-County1', 8, 2), (10, 'State2-County1-Town1', 9, 3), (11, 'State2-County1-Town1-Muncip-1', 10, 4) DECLARE @ProjectLocations TABLE (ProjectLocationId INT, ProjectId INT, LocationId INT) INSERT INTO @ProjectLocations VALUES(1, 1, 2), (2, 1, 3), (3, 1, 4), (4, 1, 11), (5, 2, 3), (6, 2, 11), (7, 3, 10), (8, 4, 11), (9, 5, 9) SELECT * FROM @Locations SELECT * FROM @ProjectLocations 作为样本。(在管理工作室中复制/粘贴)

DECLARE @FirstOutput TABLE (ProjectLocationId INT, ProjectId INT, LocationId INT, RootParentId INT)
SELECT * FROM @FirstOutput

这应该是

{{1}}

2 个答案:

答案 0 :(得分:1)

我认为以下内容适合您:

(为方便起见,我已将所有@表更改为#表)

WITH LocationHierachy (LocationId, ParentId)
AS
(
--Anchor
    SELECT  L.LocationId, ISNULL(L.ParentId, L.LocationId)
    FROM    #Locations L
    UNION ALL
--Recurse
    SELECT  H.LocationId, L.ParentId
    FROM    LocationHierachy H
    JOIN    #Locations L
            ON  L.LocationId = H.ParentId
)
SELECT  PL.ProjectLocationId, 
        PL.ProjectId, 
        PL.LocationId, 
        H.ParentId as RootParentId
FROM    #ProjectLocations PL
JOIN    LocationHierachy H
        ON  PL.LocationId = H.LocationId
JOIN    #Locations L
        ON  H.ParentId = L.LocationId
WHERE   L.ParentId IS NULL

答案 1 :(得分:0)

您需要一个递归查询,在SQL Server中使用公用表表达式实现。这是一个例子:

WITH FirstOutput (ProjectLocationId,ProjectId,LocationId,RootParentId) AS
(
  SELECT
        PL.ProjectLocationId,PL.ProjectId,L.LocationId,L.LocationId
  FROM
        ProjectLocations PL
  INNER JOIN
        Locations L ON PL.LocationId=L.LocationId
  WHERE 
        L.ParentId IS NULL
  UNION ALL 
  SELECT
  PL.ProjectLocationId,PL.ProjectId,L.LocationId,F.RootParentId
  FROM
        ProjectLocations PL
  INNER JOIN
        Locations L ON PL.LocationId=L.LocationId
  INNER JOIN
        FirstOutput F ON L.ParentId=F.LocationId
 )
 SELECT * FROM FirstOutput