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

标签 sql sql-server hierarchy

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

系统有 3 种地理类型:

  1. 国家地理(根)
  2. 区域地理(一级)
  3. 领土地理(2 级)

在数据库中,地理表看起来与此类似:

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

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

例如,如果员工 105 被分配到“南部”区域,则 XREF 表中会有一个条目,如下所示:

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

我需要做的是给定一个员工 ID,建立他们的地理层次结构。因此,员工 105 的结果将如下所示:

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

我不知道如何建立这样的数据结构。我希望有人能对这个问题有一些见解。

最佳答案

鉴于预期结果应该显示所有级别,并且级别很少,因此存在不使用递归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从垂直到水平进行分区和重组,主要查询JOIN'PIVOTed'数据到员工数据,可以通过将[trn].GeographyID更改为[trn].GeographyName

将ID更改为位置名称

可以明确划分,为每个级别定义一个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

关于sql - 在 SQL Server 中创建数据层次结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24306931/

相关文章:

mysql - Err 1292 - 截断了不正确的 DOUBLE 值

sql-server - SQL Server - 选择有条件的最新记录

html - 100% 最小高度在 Opera 中有效,但在其他浏览器中无效

emacs - Elisp 用于以纯文本形式表示目录层次结构

sql - 在 laravel [实现过滤器] 中通过 Eloquent 和急切的加载将多个表连接在一起

sql - 'Interval' 的 JPA Hibernate 查询问题

sql-server - 了解集成服务上存储的包

sql-server - SQL Server : Count how big a column value is compared to the others

c++ - 当它们在父类(super class)中被定义为纯虚拟时,如何从子类中调用所有函数?

mysql - 如何同时获得我的 friend 和 friend 的 friend ?