0

このような StaffLookup テーブルがあります。

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

スタッフ体制はこんな感じ。

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

このような SurveyResponses のリストがあります。

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

私がやろうとしていることは非常に単純に聞こえますが、きちんとした迅速な方法を見つけるのに苦労しています。Srn を受け取り、構造内のその Srn の下にあるすべてのスタッフを返す sproc を作成したいと考えています。

QuestionId のスコアが 16 の場合は、調査が完了したことを示します。入力された Srn (トップ マネージャー) の行を、そのマネージャーの下の直属部下の完了した調査の数と共に返したいと思います。その下で、元のマネージャーの下にある各マネージャーに、直属の部下ごとに完了した調査の数などを表示してもらいたいと思います。

トップ マネージャーを Joe (ABC2) に設定した場合のデータを以下に示します。

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

3 に答える 3

2

提供された情報に基づいて、これは機能すると思います。@mgrSrnこれを入力パラメータとしてSPに変換するのはそれほど難しいことではありません。

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) 
于 2010-05-11T18:40:45.837 に答える
2

これを試して:

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

出力:

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

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

出力:

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)

指定されたデータがどのように完了したかはまだわかりません。Joe は =2 を完了し、Paul は 1 を完了しました。指定されたデータを から に変更し('ABC4',16,3)('ABC6',16,3)ので、結果セットの誰かが 1 つを完了しました。

于 2010-05-11T18:50:47.803 に答える
1

編集:SQLServer2008を使用してINSERTステートメントを生成しました...

階層は生成できますが、結果は生成できません。サンプルの入力データと出力データは拘束されません。申し訳ありません。

階層に最も可能性の高い結果を結び付けるには、LevelNumが必要です。

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
于 2010-05-11T18:39:22.460 に答える