2014-06-19 69 views
2

因此,我一直負責創建SQL Server存儲過程以組裝員工的地理層次結構。在SQL Server中創建數據層次結構

該系統具有3種類型的地理:

  1. 國家地理(根)
  2. 區域地理(級別1)
  3. 領土地理學(級別2)

在數據庫地理位置表與此類似:

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

還有和員工表。一名僱員可以被分配到上述任何一個地區。

例如,如果員工105被分配到了「南方」地區有像這樣在外部參照表的條目:

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

我需要做的就是給予員工ID是什麼,建立自己的地理層次。因此,對於員工105的結果看起來像這樣:

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

我不知道如何建立這樣的數據結構。我希望有人對這個問題有所瞭解。

+0

你高興與固定在三個層次的最大深度。 t-sql遞歸查詢將是一件好事情。 –

+0

我實際上已經研究了一些,並認爲遞歸CTE將是一個潛在的答案,但我只是沒有連接點來實現解決方案,以我的pronlem使用它。有趣的是他們想要最終添加更多的地理位置或將其刪除。 – Singularity222

回答

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; 

CTEGeography分割和重新組合,從垂直到水平,主查詢JOIN的「PIVOT ED」數據到僱員數據中,ID可以通過改變[trn].GeographyID改變爲位置名稱以[trn].GeographyName

分隔CA N爲explicited定義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