Aggregierten Umfrageergebnisse rekursiv durch Manager
-
26-09-2019 - |
Frage
Ich habe eine StaffLookup Tabelle, die wie folgt aussieht.
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
Die Personalstruktur sieht wie folgt aus.
|- Jerome
|
|- Joe
||
||- Paul
|||
|||- Jack
|||
|||- Daniel
||
||- David
|||
|||- Ian
|||
|||- Helen
Ich habe eine Liste von SurveyResponses dass sieht wie folgt aus.
UserSrn | QuestionId | ResponseScore
====================================
ABC2 | 1 | 5
ABC2 | 3 | 4
ABC4 | 16 | 3
...
Was ich versuche, klingt ziemlich einfach zu tun, aber ich bin kämpfen, um eine saubere, schnelle Art und Weise zu tun, um es zu finden. Ich möchte ein sproc erstellen, die eine Srn nimmt und kehrt alles zurück das Personal unter diesem Srn in der Struktur.
Wenn es eine Punktzahl QuestionID von 16 ist dann zeigt an, dass eine abgeschlossene Umfrage. Ich möchte eine Linie für die Srn eintritt zurückzukehren (Der Top-Manager) mit einer Zählung der ausgefüllten Fragebögen für die direkten Berichte unter diesem Manager. Darunter würde ich mit einer Zählung der ausgefüllten Fragebögen für jede ihrer direkten Berichte jeden Manager unter dem ursprünglichen Manager wie und so weiter.
Ich möchte die Daten als solche unten, um zu sehen, wenn ich die Top-Manager gesetzt Joe (ABC2Ä) zu sein.
UserName | Completed | Total
============================
Joe | 2 | 2
Paul | 1 | 2
David | 0 | 2
TOTAL | 3 | 6
Lösung
Ich glaube, das funktioniert, auf der Grundlage der bereitgestellten Informationen. Es sollte nicht allzu schwierig sein, diese in eine SP zu drehen mit @mgrSrn
als Eingabeparameter.
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)
Andere Tipps
versuchen, diese:
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
OUTPUT:
UserName Completed total
---------- ----------- -----
Joe 2 ???
David 1 ???
Paul 0 ???
Bearbeiten nach OP Bemerkungen:
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
OUTPUT:
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)
Ich kann immer noch nicht sehen, wie die angegebenen Daten, Ergebnisse in Joe abgeschlossen haben = 2 und Paul 1. abgeschlossen haben änderte ich die gegebenen Daten von ('ABC4',16,3)
zu ('ABC6',16,3)
so jemand in der Ergebnismenge hätte man abgeschlossen.
Edit: Ich habe SQL Server 2008 die INSERT-Anweisungen ...
zu erzeugen,Ich kann Ihre Hierarchie, aber nicht die Ergebnisse generieren. Die Probe Eingangs- und Ausgangsdaten nicht binden, sorry.
Sie werden levelNum müssen in den Ergebnissen binden am ehesten die Hierarchie
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