在SQL Server中创建数据层次结构

时间:2014-06-19 12:43:18

标签: sql sql-server hierarchy

所以我的任务是创建一个SQL Server存储过程来组装员工的地理层次结构。

该系统有3种类型的地理位置:

  1. 国家地理(根)
  2. 区域地理(1级)
  3. 地域地理(第2级)
  4. 在数据库中,地理位置表看起来与此类似:

    GeographyID | GeographyType | GeographyName | ParentGeographyID |
    -----------------------------------------------------------------
    1             National        Nation          NULL
    2             Region          South           1
    3             Territory       Florida         2
    

    还有员工表。可以将单个员工分配到上述任何地区。

    例如,如果员工105被分配到" South"区域在XREF表中有一个条目,如下所示:

    EmployeeID | GeographyID
    ------------------------
    105           2
    

    我需要做的是给一个员工ID,建立他们的地理层次结构。因此,员工105的结果看起来像这样:

    EmployeeID | TerritoryGeographyID | RegionGeographyID | NationalGeographyID
    ---------------------------------------------------------------------------
    105          NULL                    2                    1
    

    我不知道如何设置这样的数据结构。我希望有人可以对这个问题有所了解。

1 个答案:

答案 0 :(得分:3)

鉴于预期结果应该显示所有级别,并且级别很少,有解决方案不使用递归CTE,例如

WITH G AS (
  SELECT g.GeographyID 
       , t.GeographyID TerritoryGeographyID
       , r.GeographyID RegionGeographyID
       , n.GeographyID NationalGeographyID
  FROM   Geography g
         LEFT JOIN Geography T ON (g.GeographyID = T.GeographyID)
                              AND (T.GeographyType = 'Territory')
         LEFT JOIN Geography R ON ((g.GeographyID = R.GeographyID) 
                                OR (R.GeographyID = T.ParentGeographyID))
                              AND (R.GeographyType = 'Region')
         LEFT JOIN Geography N ON ((g.GeographyID = N.GeographyID) 
                                OR (N.GeographyID = R.ParentGeographyID))
                              AND (N.GeographyType = 'National')
)
SELECT E.EmployeeID
     , TerritoryGeographyID
     , RegionGeographyID
     , NationalGeographyID
FROM   Employee E
       INNER JOIN G ON E.GeographyID = G.GeographyID;

CTE Geography被分区并从垂直方向重新组合,主要查询JOINPIVOT ed”数据到员工数据,ID可以将[trn].GeographyID更改为[trn].GeographyName

,将其更改为位置名称

可以显示分区,为每个级别定义CTE

With N AS (
  SELECT GeographyID, GeographyName
  FROM   Geography
  WHERE  GeographyType = 'National'
), R AS (
  SELECT GeographyID, GeographyName, ParentGeographyID
  FROM   Geography
  WHERE  GeographyType = 'Region'
), T AS (
  SELECT GeographyID, GeographyName, ParentGeographyID
  FROM   Geography
  WHERE  GeographyType = 'Territory'
), G AS (
  SELECT g.GeographyID 
       , t.GeographyID TerritoryGeographyID
       , r.GeographyID RegionGeographyID
       , n.GeographyID NationalGeographyID
  FROM   Geography g
         LEFT JOIN Geography T ON (g.GeographyID = T.GeographyID)
         LEFT JOIN Geography R ON (g.GeographyID = R.GeographyID)
                               OR (R.GeographyID = T.ParentGeographyID)
         LEFT JOIN Geography N ON (g.GeographyID = N.GeographyID) 
                               OR (N.GeographyID = R.ParentGeographyID)
)
SELECT E.EmployeeID
     , TerritoryGeographyID
     , RegionGeographyID
     , NationalGeographyID
FROM   Employee E
       INNER JOIN G ON E.GeographyID = G.GeographyID;

SQLFiddle demo