2010-05-11 7 views
0

J'ai une table StaffLookup qui ressemble à ceci.Résultats de l'enquête agrégée récursivement par le manager

UserSrn | UserName | ManagerSrn 
=============================== 
ABC1 | Jerome | NULL 
ABC2 | Joe  | ABC1 
ABC3 | Paul  | ABC2 
ABC4 | Jack  | ABC3 
ABC5 | Daniel | ABC3 
ABC6 | David | ABC2 
ABC7 | Ian  | ABC6 
ABC8 | Helen | ABC6 

La structure du personnel ressemble à ceci.

|- Jerome 
| 
|- Joe 
|| 
||- Paul 
||| 
|||- Jack 
||| 
|||- Daniel 
|| 
||- David 
||| 
|||- Ian 
||| 
|||- Helen 

J'ai une liste de SurveyResponses qui ressemble à ceci.

UserSrn | QuestionId | ResponseScore 
==================================== 
ABC2 | 1   | 5 
ABC2 | 3   | 4 
ABC4 | 16   | 3 
... 

Ce que je suis en train de faire des sons assez simple mais je me bats pour trouver un moyen propre, rapide de le faire. Je veux créer un sproc qui prend un Srn et renvoie tout le personnel sous ce Srn dans la structure.

S'il y a une note pour QuestionId de 16 alors cela indique un sondage complété. Je voudrais retourner une ligne pour le Srn entré (le directeur supérieur) avec un nombre de sondages remplis pour les rapports directs sous ce directeur. En vertu de cela, je voudrais que chaque gestionnaire sous le gestionnaire d'origine avec un nombre de sondages remplis pour chacun de leurs rapports directs et ainsi de suite.

Je voudrais voir les données en tant que telles ci-dessous lorsque je définis le gestionnaire supérieur sur Joe (ABC2).

UserName | Completed | Total 
============================ 
Joe  | 2   | 2 
Paul  | 1   | 2 
David | 0   | 2 
TOTAL | 3   | 6 
+2

Je ne peux pas lier vos données d'échantillon avec la sortie désirée. – gbn

+1

vous devez expliquer comment calculer 'Completed' et' Total' mieux, il semble que vos données d'échantillon ne s'additionnent pas pour obtenir ces valeurs. –

+0

Les données du tableau SurveyResponses sont représentatives. Il y a des milliers de lignes mais tant que la question 16 est répondue, elle est comptée comme une enquête terminée. –

Répondre

2

Je crois que cela fonctionne, sur la base des informations fournies. Il ne devrait pas être trop difficile de transformer ceci en SP avec @mgrSrn comme paramètre d'entrée.

declare @users table 
(UserSrn char(4) 
,UserName varchar(6) 
,ManagerSrn char(4) 
) 

INSERT @users 
     SELECT 'ABC1','Jerome',NULL 
UNION SELECT 'ABC2','Joe','ABC1' 
UNION SELECT 'ABC3','Paul','ABC2' 
UNION SELECT 'ABC4','Jack','ABC3' 
UNION SELECT 'ABC5','Daniel','ABC3' 
UNION SELECT 'ABC6','David','ABC2' 
UNION SELECT 'ABC7','Ian','ABC6' 
UNION SELECT 'ABC8','Helen','ABC6' 

declare @results table 
(UserSrn char(4) 
,QuestionId tinyint 
,ResponseScore tinyint 
) 

INSERT @results 
     SELECT 'ABC2',1,1 
UNION SELECT 'ABC4',16,1 

declare @mgrSrn char(4) 
set @mgrSrn = 'ABC2' -- Joe 


;WITH completedCTE 
AS 
(
    SELECT c.* 
      ,CASE WHEN r.UserSrn IS NOT NULL 
       THEN 1 
       ELSE 0 
      END  AS completeCount 
      ,1  AS totalCount 
    FROM  @users as c 
    LEFT JOIN @results AS r 
    ON  r.UserSrn = c.UserSrn 
    AND  r.QuestionId = 16 
) 
,recCTE 
AS 
(
    SELECT UserSrn 
      ,UserName 
      ,CAST(NULL AS CHAR(4)) AS ManagerSrn 
      ,1 as level 
      ,completeCount 
      ,totalCount 
    FROM completedCTE 
    WHERE UserSrn = @mgrSrn 

    UNION ALL 

    SELECT t.UserSrn 
      ,t.UserName 
      ,t.ManagerSrn 
      ,c.level + 1 AS level 
      ,t.completeCount AS completeCount 
      ,t.totalCount AS totalCount 
    FROM completedCTE AS t 
    JOIN recCTE AS c 
    ON c.UserSrn = t.ManagerSrn 


) 
,resultCTE 
AS 
(
    SELECT r.ManagerSrn 
      ,t.UserName 
      ,r.level 
      ,SUM(completeCount) completeCount 
      ,SUM(totalCount) totalCount 
    FROM recCTE AS r 
    JOIN @users  AS t 
    ON t.UserSrn = r.ManagerSrn 
    WHERE r.ManagerSrn IS NOT NULL 
    GROUP BY r.ManagerSrn 
      ,t.UserName 
      ,r.level 

) 
SELECT UserName 
     ,completeCount 
     ,totalCount 
FROM resultCTE 
ORDER BY level 
     ,UserName 
OPTION (MAXRECURSION 0) 
1

Edit: J'utilise SQL Server 2008 pour générer les instructions INSERT ...

Je peux générer votre hiérarchie, mais pas les résultats. Les données d'entrée et de sortie d'échantillon ne sont pas attachées, désolé.

Vous aurez besoin levelNum de lier dans les résultats les plus susceptibles de la hiérarchie

DECLARE @staff TABLE (UserSrn char(4), UserName varchar(10), ManagerSrn char(4)) 
INSERT @staff (UserSrn, UserName, ManagerSrn) 
VALUES 
('ABC1' , 'Jerome' , NULL),('ABC2' , 'Joe'  , 'ABC1'), 
('ABC3' , 'Paul'  , 'ABC2'),('ABC4' , 'Jack'  , 'ABC3'), 
('ABC5' , 'Daniel' , 'ABC3'),('ABC6' , 'David' , 'ABC2'), 
('ABC7' , 'Ian'  , 'ABC6'),('ABC8' , 'Helen' , 'ABC6') 

DECLARE @results TABLE (UserSrn char(4), QuestionId varchar(10), ResponseScore char(4)) 
INSERT @results (UserSrn, QuestionId, ResponseScore) 
VALUES ('ABC2' , 2 , 5),('ABC2' , 3  , 4),('ABC4' , 16  , 3) 

;WITH cHierarchy AS 
(
    SELECT 
     s.UserSrn, S.UserName, S.ManagerSrn, CAST('|' AS varchar(50)) AS LevelStr, 0 AS LevelNum 
    FROM 
     @staff S 
    WHERE 
     S.ManagerSrn IS NULL 
    UNION ALL 
    SELECT 
     s.UserSrn, S.UserName, S.ManagerSrn, CAST(Level + '|' AS varchar(50)), LevelNum + 1 
    FROM 
     cHierarchy C JOIN @staff S ON C.UserSrn = S.ManagerSrn 
) 
SELECT 
    * 
FROM 
    cHierarchy C 
2

essayez ceci:

DECLARE @Staff table (UserSrn char(4), UserName varchar(10), ManagerSrn char(4)) 
INSERT @Staff VALUES ('ABC1','Jerome', NULL) 
INSERT @Staff VALUES ('ABC2','Joe' ,'ABC1') 
INSERT @Staff VALUES ('ABC3','Paul' ,'ABC2') 
INSERT @Staff VALUES ('ABC4','Jack' ,'ABC3') 
INSERT @Staff VALUES ('ABC5','Daniel','ABC3') 
INSERT @Staff VALUES ('ABC6','David' ,'ABC2') 
INSERT @Staff VALUES ('ABC7','Ian' ,'ABC6') 
INSERT @Staff VALUES ('ABC8','Helen' ,'ABC6') 

DECLARE @SurveyResponses table (UserSrn char(4), QuestionId int, ResponseScore int) 
INSERT @SurveyResponses VALUES ('ABC2',1 ,5) 
INSERT @SurveyResponses VALUES ('ABC2',3 ,4) 
INSERT @SurveyResponses VALUES ('ABC6',16,3) 

DECLARE @RootUserSrn char(4) 
SET @RootUserSrn='ABC2' 

--get tree of given user 
;WITH StaffTree AS 
(
    SELECT 
     UserSrn, UserName, ManagerSrn, UserSrn AS ManagerUserSrn, UserName AS ManagerUserName, 1 AS LevelOf 
     FROM @Staff 
     WHERE [email protected] 
    UNION ALL 
     SELECT 
      s.UserSrn, s.UserName, s.ManagerSrn, t.UserSrn, t.UserName, t.LevelOf+1 
     FROM StaffTree   t 
      INNER JOIN @Staff s ON t.UserSrn=s.ManagerSrn 
     WHERE [email protected] 

) 
SELECT 
    s.UserName,COUNT(r.QuestionId) AS Completed,'???' as total 

    FROM StaffTree      s 
     LEFT OUTER JOIN @SurveyResponses r ON s.UserSrn=r.UserSrn 
    GROUP BY s.UserName,s.LevelOf 
    ORDER BY s.LevelOf 

SORTIE:

UserName Completed total 
---------- ----------- ----- 
Joe  2   ??? 
David  1   ??? 
Paul  0   ??? 

EDIT après les commentaires de OP:

DECLARE @Staff table (UserSrn char(4), UserName varchar(10), ManagerSrn char(4)) 
INSERT @Staff VALUES ('ABC1','Jerome', NULL) 
INSERT @Staff VALUES ('ABC2','Joe' ,'ABC1') 
INSERT @Staff VALUES ('ABC3','Paul' ,'ABC2') 
INSERT @Staff VALUES ('ABC4','Jack' ,'ABC3') 
INSERT @Staff VALUES ('ABC5','Daniel','ABC3') 
INSERT @Staff VALUES ('ABC6','David' ,'ABC2') 
INSERT @Staff VALUES ('ABC7','Ian' ,'ABC6') 
INSERT @Staff VALUES ('ABC8','Helen' ,'ABC6') 

DECLARE @SurveyResponses table (UserSrn char(4), QuestionId int, ResponseScore int) 
INSERT @SurveyResponses VALUES ('ABC2',1 ,5) 
INSERT @SurveyResponses VALUES ('ABC2',3 ,4) 
INSERT @SurveyResponses VALUES ('ABC6',16,3) 

DECLARE @RootUserSrn char(4) 
SET @RootUserSrn='ABC2' 

--get tree of given user 
;WITH StaffTree AS 
(
    SELECT 
     UserSrn, UserName, ManagerSrn, UserSrn AS ManagerUserSrn, UserName AS ManagerUserName, 1 AS LevelOf 
     FROM @Staff 
     WHERE [email protected] 
    UNION ALL 
     SELECT 
      s.UserSrn, s.UserName, s.ManagerSrn, t.UserSrn, t.UserName, t.LevelOf+1 
     FROM StaffTree   t 
      INNER JOIN @Staff s ON t.UserSrn=s.ManagerSrn 
     WHERE [email protected] 

) 
, MINLevel AS (
    SELECT MIN(LevelOf) AS MinLevelOf FROM StaffTree 
) 
, TotalLevel AS (
    SELECT 
     SUM(CASE WHEN s.LevelOf !=m.MinLevelOf THEN 1 ELSE 0 END) AS TotalOf 
     FROM StaffTree   s 
      CROSS JOIN MINLevel m 
) 
,Results AS (
    SELECT 
     s.UserName,SUM(CASE WHEN r.QuestionId=16 THEN 1 ELSE 0 END) AS Completed,t.TotalOf as total,s.LevelOf 

     FROM StaffTree      s 
      LEFT OUTER JOIN @SurveyResponses r ON s.UserSrn=r.UserSrn 
      CROSS JOIN TotalLevel    t 
     GROUP BY s.UserName,s.LevelOf,t.TotalOf 
) 
SELECT 
    UserName,Completed,total, 1,LevelOf 
    FROM Results 
UNION ALL 
    SELECT 
     'TOTAL',SUM(Completed),SUM(total),2,0 
     FROM Results 
ORDER BY 4,5 

SORTIE:

UserName Completed total     LevelOf 
---------- ----------- ----------- ----------- ----------- 
Joe  0   2   1   1 
David  1   2   1   2 
Paul  0   2   1   2 
TOTAL  1   6   2   0 

(4 row(s) affected) 

Je ne peux pas voir comment les données fournies, les résultats de Joe ayant complété = 2 et Paul ayant terminé 1. J'ai changé les données fournies de ('ABC4',16,3) à ('ABC6',16,3) si quelqu'un dans le jeu de résultats aurait un terminé.

+0

Je ne sais pas comment calculer 'Completed' et' total', la question n'est pas claire et les données de l'échantillon semblent incohérentes à partir des résultats donnés. –

+0

Terminé est le nombre de personnes ayant répondu à la question 16. Total est le nombre de personnes dans ce groupe particulier qui doivent répondre à l'enquête. Je vais modifier la question merci pour les mots. –

+0

Où est stockée l'information «requise pour prendre l'enquête»? –