2011-03-21 13 views
1

を(SQL Serverを)数:再帰クエリと私はこれら四つの単純化されたテーブルを使用してクエリを記述しようとしている

組織
(PK)は、(FK) 組織名

をOrganizationID

をParentOrganizationID

人員
(pk)PersonnelID
(fk)OrganizationID
名前

イベント
(PK)イベントID
EVENTNAME

のEventLog
(PK)はPersonnelID
(PK)イベントID
TimeOfParticipation

私が作成したいですイベントIDと組織IDをパラメートとして使用するクエリ組織の名前、組織と子組織の総数、および組織のイベントの参加者の総数とその子を返すテーブルを返します。戻り値の例は、次のとおりです。

OrganizationName | TotalNumberInOrganization | TotalParticipatingInEvent 
TopOrganization |   200    |   150  
SecondTier1  |   150    |   100 
    Tier1Child  |   50    |    50 
    Tier1Child2  |   50    |    25 
SecondTier2  |   25    |    25 

上位組織は、すべての子SecondTier1とSecondTier2の合計です。 SecondTier1は、すべての子、Teir1ChildとTier1Child2、およびそれ自身の合計です。これは、すべての子供と合計を計算することになります。

私は再帰的なCTEを使用して1つのエントリを返す方法を知っています。たとえば、トップ組織の合計だけですが、すべての組織とその子供の合計を取得する方法はわかりません。どんな助けもありがとう。

ここで要求されるのは、私が組織について単一の行を返すために使用する手順です。

UNIONに 'U'を追加すると何らかの理由でネットワークエラーが発生し、編集できなくなります。

@OrganizationID uniqueidentifier 
@EventID uniqueidentifier 

WITH OrganizationList(OrganizationID) AS 
    (SELECT Organization.OrganizationID 
    FROM Organization 
    WHERE OrganizationID = @OrganizationID 
    NION ALL 
    SELECT Organization.OrganizationID 
    FROM Organization 
    INNER JOIN OrganizationList ON Organization.ParentOrganizationID = OrganizationList.OrganizationID) 

SELECT OrganizationAbbreviation, 

     (SELECT COUNT(*) 
     FROM Personnel 
     WHERE Personnel.OrganizationID IN (SELECT OrganizationID FROM OrganizationList)) 
     AS OrganizationTotal, 

     (SELECT COUNT(*) 
     FROM Personnel 
     INNER JOIN EventLog ON EventLog.PersonnelID = Personnel.PersonnelID 
     WHERE Personnel.OrganizationID IN (SELECT OrganizationID FROM OrganizationList) 
       AND EventLog.EventID = @EventID) 
     AS TotalPresent 
FROM Organization 
WHERE OrganizationID = @OrganizationID 
+0

問題があり、 SQL Serverの再帰的なCTEにはいくつかの制限があります。特に、再帰的な部分にはグループ化を含めることはできません。したがって、集約します。そのような理由から、私は実際には、単一のエントリ、特に上位レベルのものに対するあなたのソリューションが何であるかを知りたいと思います。投稿してもよろしいですか?ここに誰かがあなたのケースのための完全なソリューションにそれを開発する方法について良いアイデアを持っているかもしれません。 –

答えて

2

私はこれがあなたのために働くだろうと思う:

WITH OrganizationTree (RootOrganizationID, OrganizationID) 
AS 
(
--Anchor 
    SELECT O.OrganizationID, O.OrganizationID 
    FROM Organization O 
    UNION ALL 
--Recurse 
    SELECT T.RootOrganizationID, O.OrganizationID 
    FROM OrganizationTree T 
    JOIN Organization O 
     ON O.ParentOrganizationId = T.OrganizationID 
) 
--execute 
SELECT P.OrganizationName, 
     SUM(ISNULL(PPL.NumberInOrganization, 0)) AS TotalNumberInOrganization, 
     SUM(ISNULL(EVT.NumberParticipatingInEvent, 0)) AS TotalNumberParticipatingInEvent 
FROM OrganizationTree T 
JOIN Organization P 
     ON T.RootOrganizationID = P.OrganizationID 
LEFT 
JOIN  
(
     SELECT P.OrganizationID, 
       COUNT(*) AS NumberInOrganization 
     FROM Personnel P 
     GROUP BY P.OrganizationID 
) PPL 
     ON PPL.OrganizationID = T.OrganizationID 
LEFT 
JOIN 
(
     SELECT P.OrganizationID, 
       COUNT(*) AS NumberParticipatingInEvent 
     FROM EventLog EL 
     JOIN Personnel P 
       ON EL.PersonnelID = P.PersonnelID 
     GROUP BY P.OrganizationID 
) EVT 
     ON EVT.OrganizationID = T.OrganizationID 
GROUP BY T.RootOrganizationID, P.OrganizationName 

あなたの出力例のようにインデントを持っている必要がある場合は、これは動作するはずです:

WITH OrganizationTree (RootOrganizationID, OrganizationID) 
AS 
(
--Anchor 
    SELECT O.OrganizationID, O.OrganizationID 
    FROM Organization O 
    UNION ALL 
--Recurse 
    SELECT T.RootOrganizationID, O.OrganizationID 
    FROM OrganizationTree T 
    JOIN Organization O 
     ON O.ParentOrganizationId = T.OrganizationID 
) 
--execute 
SELECT SPACE(L.OrganizationLevel) + P.OrganizationName AS FormattedOrganizationName, 
     P.OrganizationName, 
     SUM(ISNULL(PPL.NumberInOrganization, 0)) AS TotalNumberInOrganization, 
     SUM(ISNULL(EVT.NumberParticipatingInEvent, 0)) AS TotalNumberParticipatingInEvent 
FROM OrganizationTree T 
JOIN  
(
     SELECT L.OrganizationID, 
       (COUNT(*) - 1) AS OrganizationLevel 
     FROM OrganizationTree L 
     GROUP BY L.OrganizationID 
) L 
    ON T.RootOrganizationID = L.OrganizationID 
JOIN Organization P 
     ON T.RootOrganizationID = P.OrganizationID 
LEFT 
JOIN  
(
     SELECT P.OrganizationID, 
       COUNT(*) AS NumberInOrganization 
     FROM Personnel P 
     GROUP BY P.OrganizationID 
) PPL 
     ON PPL.OrganizationID = T.OrganizationID 
LEFT 
JOIN 
(
     SELECT P.OrganizationID, 
       COUNT(*) AS NumberParticipatingInEvent 
     FROM EventLog EL 
     JOIN Personnel P 
       ON EL.PersonnelID = P.PersonnelID 
     GROUP BY P.OrganizationID 
) EVT 
     ON EVT.OrganizationID = T.OrganizationID 
GROUP BY T.RootOrganizationID, L.OrganizationLevel, P.OrganizationName 
+0

TotalNumberParticipatingInEventを「1つ以上のイベントに参加する個別の人数」または「各イベントに参加する個体の合計」とするかどうかはわかりません。上のクエリは後者を行いますが、前のクエリに変更するのは簡単です。サブクエリを変更するだけです... –

+0

私は技術が特定の名前を取得するかどうかはわかりません - 少なくとも私が知っているものはありません...! –

関連する問題