2014-05-12 107 views
0

我希望有人能幫助我。我想要一份報告,其中包含計算組織結構的報告。SQL Server:遞歸CTE?從組織結構創建報告

CREATE TABLE Organistation 
    (
    KeySubCompany NUMERIC(12, 0) , 
    O1 VARCHAR(255) , 
    O2 VARCHAR(255) , 
    O3 VARCHAR(255) , 
    O4 VARCHAR(255) , 
    O5 VARCHAR(255) , 
    O6 VARCHAR(255) , 
    O7 VARCHAR(255) , 
    O8 VARCHAR(255) , 
    O9 VARCHAR(255) , 
    O10 VARCHAR(255) , 
    O11 VARCHAR(255) , 
    O12 VARCHAR(255) 
) 

INSERT INTO dbo.Organistation 
      (KeySubCompany, O1, O2, O3, O4, O5, O6, O7, O8, O9, O10, O11, O12) 
VALUES (1, 'World', 'Europe', 'Germany', 'Berlin', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), 
      (2, 'World', 'Europe', 'Germany', 'Hamburg', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), 
      (3, 'World', 'Europe', 'Italy', 'Rom', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), 
      (4, 'World', 'Europe', 'Italy', 'Neapel', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), 
      (5, 'World', 'Europe', 'Germany', 'Dresden', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), 
      (6, 'World', 'North America', 'Canada', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL), 
      (7, 'World', 'North America', 'USA', 'New York', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)   


CREATE TABLE COMPANY 
    (
    KeyCompany NUMERIC(12, 0) , 
    NAME VARCHAR(255) , 
    viewdepth INTEGER 
) 


INSERT INTO dbo.COMPANY 
      (KeyCompany, NAME, viewdepth) 
VALUES (1, 'Main', 2) 

CREATE TABLE SUBCOMPANY 
    (
    KeySubCompany NUMERIC(12, 0) , 
    KeyCompany NUMERIC(12, 0) , 
    NameSubCompany VARCHAR(255) 
) 


INSERT INTO dbo.SUBCOMPANY 
      (KeySubCompany, KeyCompany, NameSubCompany) 
VALUES (1, 1, '1_SubCompany'), 
      (2, 1, '2_SubCompany'), 
      (3, 1, '3_SubCompany'), 
      (4, 1, '4_SubCompany'), 
      (5, 1, '5_SubCompany'), 
      (6, 1, '6_SubCompany'), 
      (7, 1, '7_SubCompany') 

CREATE TABLE EMPLOYEES 
    (
    EMPLOYID NUMERIC(12, 0) , 
    KeySubCompany NUMERIC(12, 0) , 
    NAME VARCHAR(255) 
) 


INSERT INTO dbo.EMPLOYEES 
      (EMPLOYID, KeySubCompany, NAME) 
VALUES (1, 1, 'Winny'), 
      (1, 1, 'Justin'), 
      (1, 3, 'Mary'), 
      (1, 4, 'Leon'), 
      (1, 4, 'Marcy'), 
      (1, 7, 'Peter') 

我期望的結果是:

enter image description here

在表Company我希望能夠配置組織結構的深度在我的報告(目前視圖深度3)

我目前的解決方案:

WITH CompanyRollup 
    AS (SELECT C.KeyCompany , 
        CASE WHEN (GROUPING(O.O1) = 1) THEN '' 
         ELSE O.O1 
        END AS O1 , 
        NULL AS O2 , 
        NULL AS O3 , 
        NULL AS O4 , 
        NULL AS O5 , 
        NULL AS O6 , 
        NULL AS O7 , 
        NULL AS O8 , 
        NULL AS O9 , 
        NULL AS O10 , 
        NULL AS O11 , 
        NULL AS O12 , 
        1 AS viewDepth 
     FROM  dbo.COMPANY C 
        INNER JOIN dbo.SUBCOMPANY SC ON SC.KeyCompany = C.KeyCompany 
                AND (C.viewdepth + 1) = 1 
        INNER JOIN dbo.Organistation O ON O.KeySubCompany = SC.KeySubCompany 
     GROUP BY C.KeyCompany , 
        O.O1 
        WITH ROLLUP 
     UNION 
     SELECT C.KeyCompany , 
        CASE WHEN (GROUPING(O.O1) = 1) THEN '' 
         ELSE O.O1 
        END AS O1 , 
        CASE WHEN (GROUPING(O.O2) = 1) THEN '' 
         ELSE O.O2 
        END AS O2 , 
        NULL AS O3 , 
        NULL AS O4 , 
        NULL AS O5 , 
        NULL AS O6 , 
        NULL AS O7 , 
        NULL AS O8 , 
        NULL AS O9 , 
        NULL AS O10 , 
        NULL AS O11 , 
        NULL AS O12 , 
        2 AS viewDepth 
     FROM  dbo.COMPANY C 
        INNER JOIN dbo.SUBCOMPANY SC ON SC.KeyCompany = C.KeyCompany 
                AND (C.viewdepth + 1) = 2 
        INNER JOIN dbo.Organistation O ON O.KeySubCompany = SC.KeySubCompany 
     GROUP BY C.KeyCompany , 
        O.O1 , 
        O.O2 
        WITH ROLLUP 
     UNION 
     SELECT C.KeyCompany , 
        CASE WHEN (GROUPING(O.O1) = 1) THEN '' 
         ELSE O.O1 
        END AS O1 , 
        CASE WHEN (GROUPING(O.O2) = 1) THEN '' 
         ELSE O.O2 
        END AS O2 , 
        CASE WHEN (GROUPING(O.O3) = 1) THEN '' 
         ELSE O.O3 
        END AS O3 , 
        NULL AS O4 , 
        NULL AS O5 , 
        NULL AS O6 , 
        NULL AS O7 , 
        NULL AS O8 , 
        NULL AS O9 , 
        NULL AS O10 , 
        NULL AS O11 , 
        NULL AS O12 , 
        3 AS viewDepth 
     FROM  dbo.COMPANY C 
        INNER JOIN dbo.SUBCOMPANY SC ON SC.KeyCompany = C.KeyCompany 
                AND (C.viewdepth + 1) = 3 
        INNER JOIN dbo.Organistation O ON O.KeySubCompany = SC.KeySubCompany 
     GROUP BY C.KeyCompany , 
        O.O1 , 
        O.O2 , 
        O.O3 
        WITH ROLLUP 
     ) 

SELECT CR.KeyCompany , 
     SUM(SE.EMPLOYID) CountEmployees , 
     CR.O1 , 
     NULL AS O2, 
     NULL AS O3, 
     NULL AS O4, 
     NULL AS O5, 
     NULL AS O6, 
     NULL AS O7, 
     NULL AS O8, 
     NULL AS O9, 
     NULL AS O10, 
     NULL AS O11, 
     NULL AS O12 
FROM CompanyRollup CR 
     INNER JOIN (SELECT DISTINCT 
          KeyCompany , 
          EMPLOYID 
        FROM dbo.EMPLOYEES E 
          INNER JOIN dbo.SUBCOMPANY SSC ON SSC.KeySubCompany = E.KeySubCompany 
        ) SE ON SE.KeyCompany = CR.KeyCompany 
     INNER JOIN (SELECT SSSC.KeyCompany , 
          SO.* 
        FROM dbo.SUBCOMPANY SSSC 
          INNER JOIN dbo.Organistation SO ON SSSC.KeySubCompany = SO.KeySubCompany 
        ) SOO ON SOO.KeyCompany = CR.KeyCOmpany 
          AND (CR.O1 = '' 
            OR ISNULL(CR.O1, '') = ISNULL(SOO.O1, '') 
           ) 
WHERE CR.Viewdepth = 1 
GROUP BY CR.KeyCompany , 
     CR.O1 

    UNION 
    SELECT CR.KeyCompany , 
     SUM(SE.EMPLOYID) CountEmployees , 
     CR.O1 , 
     CR.O2 , 
     NULL AS O3, 
     NULL AS O4, 
     NULL AS O5, 
     NULL AS O6, 
     NULL AS O7, 
     NULL AS O8, 
     NULL AS O9, 
     NULL AS O10, 
     NULL AS O11, 
     NULL AS O12 
FROM CompanyRollup CR 
     INNER JOIN (SELECT DISTINCT 
          KeyCompany , 
          EMPLOYID 
        FROM dbo.EMPLOYEES E 
          INNER JOIN dbo.SUBCOMPANY SSC ON SSC.KeySubCompany = E.KeySubCompany 
        ) SE ON SE.KeyCompany = CR.KeyCompany 
     INNER JOIN (SELECT SSSC.KeyCompany , 
          SO.* 
        FROM dbo.SUBCOMPANY SSSC 
          INNER JOIN dbo.Organistation SO ON SSSC.KeySubCompany = SO.KeySubCompany 
        ) SOO ON SOO.KeyCompany = CR.KeyCOmpany 
          AND (CR.O1 = '' 
            OR ISNULL(CR.O1, '') = ISNULL(SOO.O1, '') 
           )AND (CR.O2 = '' 
            OR ISNULL(CR.O2, '') = ISNULL(SOO.O2, '') 
           ) 
WHERE CR.Viewdepth = 2 
GROUP BY CR.KeyCompany , 
     CR.O1, 
     CR.O2 
    UNION 
    SELECT CR.KeyCompany , 
     SUM(SE.EMPLOYID) CountEmployees , 
     CR.O1 AS O1, 
     CR.O2 AS O2, 
     CR.O3 AS O3, 
     NULL AS O4, 
     NULL AS O5, 
     NULL AS O6, 
     NULL AS O7, 
     NULL AS O8, 
     NULL AS O9, 
     NULL AS O10, 
     NULL AS O11, 
     NULL AS O12 
FROM CompanyRollup CR 
     INNER JOIN (SELECT DISTINCT 
          KeyCompany , 
          EMPLOYID 
        FROM dbo.EMPLOYEES E 
          INNER JOIN dbo.SUBCOMPANY SSC ON SSC.KeySubCompany = E.KeySubCompany 
        ) SE ON SE.KeyCompany = CR.KeyCompany 
     INNER JOIN (SELECT SSSC.KeyCompany , 
          SO.* 
        FROM dbo.SUBCOMPANY SSSC 
          INNER JOIN dbo.Organistation SO ON SSSC.KeySubCompany = SO.KeySubCompany 
        ) SOO ON SOO.KeyCompany = CR.KeyCOmpany 
          AND (CR.O1 = '' 
            OR ISNULL(CR.O1, '') = ISNULL(SOO.O1, '') 
           )AND (CR.O2 = '' 
            OR ISNULL(CR.O2, '') = ISNULL(SOO.O2, '') 
           ) AND (CR.O3 = '' 
            OR ISNULL(CR.O3, '') = ISNULL(SOO.O3, '') 
           ) 
WHERE CR.Viewdepth = 3 
GROUP BY CR.KeyCompany , 
     CR.O1, 
     CR.O2, 
     CR.O3.... UNION.... UNTIL O12 

.....等等,直到O12

正如你所看到的,它幾乎只是複製/粘貼組織結構有點不同。

有沒有一種方法來創建一個「乾淨」的版本來創建一個這樣的報告?

我創建具有相同的結構,我的數據庫/表我目前所面對的一個「簡單」,所以它不可能改變表結構。

在此先感謝。

之前,我忘了SQL Fiddle Demo

+3

是的。使用CTE。閱讀http://technet.microsoft.com/en-us/library/ms190766(v=sql.105).aspx和http://msdn.microsoft.com/en-gb/library/ms175972.aspx – podiluska

+0

ok thx我會檢查出來 – WhoisIt

+0

嗯對不起IAM這種新的..這個檢查出來,但我怎麼能創建一個這樣的CTE報告? – WhoisIt

回答

1

看看下面的東西。這是我知道的創建分層列表的最簡單的方法。如果您無法更改基礎表結構,則在#temp表中準備數據,然後再製作10層嵌套CTE會更容易。

SQLFiddle

CREATE TABLE Grp_lvl_1 (
    Id INT IDENTITY(1,1) NOT NULL, 
    Name NVARCHAR(50)) 

CREATE TABLE Grp_lvl_2 (
    Id INT IDENTITY(1,1) NOT NULL, 
    lvl_1_Id INT, 
    Name NVARCHAR(50)) 

INSERT Grp_lvl_1 (Name) VALUES 
('Continent_1'), 
('Continent_2'), 
('Continent_3') 

INSERT Grp_lvl_2 (lvl_1_Id, Name) VALUES 
(1,'Country_1'), 
(1,'Country_2'), 
(1,'Country_3'), 
(2,'Country_4'), 
(2,'Country_5'), 
(2,'Country_6'), 
(3,'Country_7'), 
(3,'Country_8'), 
(3,'Country_9') 

SELECT Grp_lvl_1.Name col1, Grp_lvl_2.Name col2 
FROM Grp_lvl_1 INNER JOIN 
Grp_lvl_2 ON Grp_lvl_1.Id = Grp_lvl_2.lvl_1_Id 
1

沒有,有沒有必要遞歸CTE,一個ROLLUP能得到您的報告

如果使用SQLServer的2008年或在HAVING更好的條件列表可取代通過使用GROUPING_ID的單個條件,它返回ROLLUP,CUBEGROUPING SETS中的分組級別,作爲位圖的int值,因此該值需要轉換,位圖處於相同的orde所以你希望看到更高的細節越少,將使用GROUPING_ID的值作爲下限。

SELECT c.KeyCompany 
    , COUNT(e.EMPLOYID) CountEmployees 
    , o.o1, o.o2, o.o3, o.o4, o.o5, o.o6 
    , o.o7, o.o8, o.o9, o.o10, o.o11, o.o12 
FROM Organistation o 
     INNER JOIN SUBCOMPANY s ON o.KeySubCompany = s.KeySubCompany 
     INNER JOIN COMPANY c ON s.KeyCompany = c.KeyCompany 
     INNER JOIN EMPLOYEES e ON o.KeySubCompany = e.KeySubCompany 
GROUP BY c.KeyCompany, RollUp(o.o1, o.o2, o.o3, o.o4, o.o5, o.o6 
          , o.o7, o.o8, o.o9, o.o10, o.o11, o.o12) 
HAVING GROUPING(o.o1) = 0 
    AND GROUPING_ID(o.o1, o.o2, o.o3, o.o4, o.o5, o.o6 
       , o.o7, o.o8, o.o9, o.o10, o.o11, o.o12) 
    > power(2, 11 - (MAX(c.viewdepth) + 1)) 
ORDER BY COUNT(e.EMPLOYID) 

SQLFiddle演示

如果您使用SQLServer的2005年或更早versione查詢會更詳細

SELECT c.KeyCompany 
    , COUNT(e.EMPLOYID) CountEmployees 
    , o.o1, o.o2, o.o3, o.o4, o.o5, o.o6 
    , o.o7, o.o8, o.o9, o.o10, o.o11, o.o12 
FROM Organistation o 
     INNER JOIN SUBCOMPANY s ON o.KeySubCompany = s.KeySubCompany 
     INNER JOIN COMPANY c ON s.KeyCompany = c.KeyCompany 
     INNER JOIN EMPLOYEES e ON o.KeySubCompany = e.KeySubCompany 
GROUP BY c.KeyCompany, RollUp(o.o1, o.o2, o.o3, o.o4, o.o5, o.o6 
          , o.o7, o.o8, o.o9, o.o10, o.o11, o.o12) 
HAVING GROUPING(o.o1) = 0 
    AND (GROUPING(o.o1) = 1 OR (GROUPING(o.o1) = 0 AND MAX(c.viewdepth) + 1 >= 1)) 
    AND (GROUPING(o.o2) = 1 OR (GROUPING(o.o2) = 0 AND MAX(c.viewdepth) + 1 >= 2)) 
    AND (GROUPING(o.o3) = 1 OR (GROUPING(o.o3) = 0 AND MAX(c.viewdepth) + 1 >= 3)) 
    AND (GROUPING(o.o4) = 1 OR (GROUPING(o.o4) = 0 AND MAX(c.viewdepth) + 1 >= 4)) 
    AND (GROUPING(o.o5) = 1 OR (GROUPING(o.o5) = 0 AND MAX(c.viewdepth) + 1 >= 5)) 
    AND (GROUPING(o.o6) = 1 OR (GROUPING(o.o6) = 0 AND MAX(c.viewdepth) + 1 >= 6)) 
    AND (GROUPING(o.o7) = 1 OR (GROUPING(o.o7) = 0 AND MAX(c.viewdepth) + 1 >= 7)) 
    AND (GROUPING(o.o8) = 1 OR (GROUPING(o.o8) = 0 AND MAX(c.viewdepth) + 1 >= 8)) 
    AND (GROUPING(o.o9) = 1 OR (GROUPING(o.o9) = 0 AND MAX(c.viewdepth) + 1 >= 9)) 
    AND (GROUPING(o.o10) = 1 OR (Grouping(o.o10) = 0 
          AND MAX(c.viewdepth) + 1 >= 10)) 
    AND (GROUPING(o.o11) = 1 OR (GROUPING(o.o11) = 0 
          AND MAX(c.viewdepth) + 1 >= 11)) 
    AND (GROUPING(o.o12) = 1 OR (GROUPING(o.o12) = 0 
          AND MAX(c.viewdepth) + 1 >= 12)) 
ORDER BY COUNT(e.EMPLOYID) 

的訣竅是在HAVING,線條

(GROUPING(o.o4) = 1 OR (GROUPING(o.o4) = 0 AND MAX(c.viewdepth) + 1 >= 4)) 

刪除返回的所有行3210未分組(Grouping(o.o4) = 1)或深度低於最大需求(GROUPING(o.o4) = 0 AND MAX(c.viewdepth) + 1 >= 4))。

SQLFiddle demo