所以我的任务是创建一个SQL Server存储过程来组装员工的地理层次结构。
该系统有3种类型的地理位置:
在数据库中,地理位置表看起来与此类似:
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
我不知道如何设置这样的数据结构。我希望有人可以对这个问题有所了解。
答案 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
被分区并从垂直方向重新组合,主要查询JOIN
“PIVOT
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;