sondaggio Aggregate risultati ricorsivamente dal responsabile
-
26-09-2019 - |
Domanda
Ho una tabella StaffLookup che assomiglia a questo.
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
Gli sguardi struttura del personale come questo.
|- Jerome
|
|- Joe
||
||- Paul
|||
|||- Jack
|||
|||- Daniel
||
||- David
|||
|||- Ian
|||
|||- Helen
Ho una lista di SurveyResponses che assomiglia a questo.
UserSrn | QuestionId | ResponseScore
====================================
ABC2 | 1 | 5
ABC2 | 3 | 4
ABC4 | 16 | 3
...
Quello che sto cercando di fare suoni piuttosto semplice, ma sto lottando per trovare un modo pulito, rapido di farlo. Voglio creare uno sProc che prende uno SRN e ritorna tutto il personale sotto che SRN nella struttura.
Se c'è un punteggio per QuestionID di 16 allora che indica un sondaggio completato. Vorrei tornare una linea per l'entrò la SRN (Il top manager), con un conteggio di indagini completate per i rapporti diretti ai sensi di tale responsabile. Sotto che vorrei ogni responsabile sotto il manager originale con un conteggio di indagini completate per ciascuno dei loro rapporti diretti e così via.
Mi piacerebbe vedere i dati come tali sotto quando ho creato il top manager di essere Joe (ABC2).
UserName | Completed | Total
============================
Joe | 2 | 2
Paul | 1 | 2
David | 0 | 2
TOTAL | 3 | 6
Soluzione
Credo che questo lavori, sulla base delle informazioni fornite. Non dovrebbe essere troppo difficile da trasformare questo in un SP con @mgrSrn
come parametro di input.
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)
Altri suggerimenti
provare questo:
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 UserSrn=@RootUserSrn
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 s.ManagerSrn=@RootUserSrn
)
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
USCITA:
UserName Completed total
---------- ----------- -----
Joe 2 ???
David 1 ???
Paul 0 ???
Modifica , dopo i commenti di 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 UserSrn=@RootUserSrn
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 s.ManagerSrn=@RootUserSrn
)
, 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
USCITA:
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)
non riesco ancora a vedere come i dati forniti, i risultati a Joe che hanno completato = 2 e Paolo che hanno completato 1. Ho cambiato i dati forniti da ('ABC4',16,3)
a ('ABC6',16,3)
così qualcuno nel set di risultati sarebbe uno completato.
Edit: ho usato 2008 SQL Server per generare le istruzioni INSERT ...
I in grado di generare la gerarchia, ma non i risultati. I dati di ingresso e di uscita del campione non legano, spiacente.
Si avrà bisogno levelNum di legare i risultati più probabile che la gerarchia
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