2016-05-10 14 views
2

この質問は、以前に解決した質問(Vladimir Baranovに感謝します)から続き、SQL Server - CTE Recursive SUM Value From Different Tableにアクセスできます。SQL Server - CTE再帰的な、子のデータのループ?

データ構造は、従業員の出席日を示す EmOvertimeに「AttdDate」という名前の別の列があることを除いて、以前とほぼ同じです。データの例はEmOvertimeです。 CsOrganizationEmHisOrganizationから

Table Name : EmOvertime 
EmpId AttdDate  TotalOtReal  
2  2016-05-09 2.00   
2  2016-05-10 2.00   
2  2016-05-11 2.00  
2  2016-05-12 2.00   
3  2016-05-12 3.00 

データは、前の質問と同じです。私は、12月 - 2016年にそのTotalHours値を持つすべての組織データを表示したいとし、クエリは次のようになります:

WITH 
CTE_OrgHours 
AS 
(
SELECT 
    Org.OrgId 
    ,Org.OrgParentId 
    ,Org.OrgName 
    ,ISNULL(Overtime.TotalOtReal, 0) AS SumHours 
    ,Overtime.AttdDate 
FROM 
    CsOrganization AS Org 
    LEFT JOIN EmHisOrganization AS Emp ON Emp.OrgId = Org.OrgID 
    LEFT JOIN EmOvertime AS Overtime ON Overtime.EmpId = Emp.EmpId 
GROUP BY 
    Org.OrgId 
    ,Org.OrgParentId 
    ,Org.OrgName 
    ,Overtime.TotalOtReal 
    ,Overtime.AttdDate 
) 
,CTE_Recursive 
AS 
(
SELECT 
    CTE_OrgHours.OrgId 
    ,CTE_OrgHours.OrgParentId 
    ,CTE_OrgHours.OrgName 
    ,CTE_OrgHours.SumHours 
    ,CTE_OrgHours.AttdDate 
    ,1 AS Lvl 
    ,CTE_OrgHours.OrgId AS StartOrgId 
    ,CTE_OrgHours.OrgName AS StartOrgName 
FROM CTE_OrgHours 

UNION ALL 

SELECT 
    CTE_OrgHours.OrgId 
    ,CTE_OrgHours.OrgParentId 
    ,CTE_OrgHours.OrgName 
    ,CTE_OrgHours.SumHours 
    ,CTE_OrgHours.AttdDate 
    ,CTE_Recursive.Lvl + 1 AS Lvl 
    ,CTE_Recursive.StartOrgId 
    ,CTE_Recursive.StartOrgName 
FROM 
    CTE_OrgHours 
    INNER JOIN CTE_Recursive ON CTE_Recursive.OrgId = CTE_OrgHours.OrgParentId 
) 
SELECT 
    StartOrgId 
    ,StartOrgName 
    ,SUM(SumHours) AS TotalHours 
FROM CTE_Recursive 
WHERE AttdDate = '2016-05-12' 
GROUP BY 
    StartOrgId 
    ,StartOrgName 
ORDER BY StartOrgId 

しかし、クエリの結果は次のように表示されます。

OrgId  OrgName  TotalHours  
1   X COMPANY  14.00 
2   Administrator 14.00 
3   Adm 1   12.00 
4   Adm 2   0.00 
5   Adm 1_1  0.00 

正しいものは次のようにする必要がありますが:

Desired Output 
OrgId  OrgName  TotalHours  
1   X COMPANY  5.00 
2   Administrator 5.00 
3   Adm 1   3.00 
4   Adm 2   0.00 
5   Adm 1_1  0.00 

子供のデータがEmOvertimeで、その親のデータの量としてループしているようですは4つの同じIDを持ちます。したがって、値12.00が示されています。この問題を解決するには?

ご協力いただければ幸いです。

答えて

1

特定の日付に興味があれば簡単です。

WHEREフィルタをクエリの前の部分に移動する必要があるようです。 CTE_OrgHoursCTE_OrgHoursは、関連する時間の合計で組織ごとに1行を返す必要があります。このクエリではすべてのフィルタリングが行われます。再帰的な部分は、後でCTE_OrgHoursに組織ごとに1つの行を持つことが予想されます。

WITH 
CTE_OrgHours 
AS 
(
    SELECT 
     Org.OrgId 
     ,Org.OrgParentId 
     ,Org.OrgName 
     ,ISNULL(SUM(Overtime.TotalOtReal), 0) AS SumHours 
    FROM 
     CsOrganization AS Org 
     LEFT JOIN EmHisOrganization AS Emp ON Emp.OrgId = Org.OrgID 
     LEFT JOIN EmOvertime AS Overtime 
      ON Overtime.EmpId = Emp.EmpId 
      AND Overtime.AttdDate = '2016-05-12' 
    GROUP BY 
     Org.OrgId 
     ,Org.OrgParentId 
     ,Org.OrgName 
) 
,CTE_Recursive 
AS 
(
    SELECT 
     CTE_OrgHours.OrgId 
     ,CTE_OrgHours.OrgParentId 
     ,CTE_OrgHours.OrgName 
     ,CTE_OrgHours.SumHours 
     ,1 AS Lvl 
     ,CTE_OrgHours.OrgId AS StartOrgId 
     ,CTE_OrgHours.OrgName AS StartOrgName 
    FROM CTE_OrgHours 

    UNION ALL 

    SELECT 
     CTE_OrgHours.OrgId 
     ,CTE_OrgHours.OrgParentId 
     ,CTE_OrgHours.OrgName 
     ,CTE_OrgHours.SumHours 
     ,CTE_Recursive.Lvl + 1 AS Lvl 
     ,CTE_Recursive.StartOrgId 
     ,CTE_Recursive.StartOrgName 
    FROM 
     CTE_OrgHours 
     INNER JOIN CTE_Recursive ON CTE_Recursive.OrgId = CTE_OrgHours.OrgParentId 
) 
SELECT 
    StartOrgId 
    ,StartOrgName 
    ,SUM(SumHours) AS TotalHours 
FROM CTE_Recursive 
GROUP BY 
    StartOrgId 
    ,StartOrgName 
ORDER BY StartOrgId; 
+0

これまでの試みでは、最終的なSELECTからWHERE句をCTE_OrgHoursに移動しようとしましたが、うまくいかなかったのです。しかし、その後、ON句に「AND Overtime.AttdDate = '2016-05-12'」を追加するだけでは、その仕事は実現しないことに気付きませんでした。おかげさまで、本当にありがとうございました。これを答えにしました! – Reynaldi

+0

@Reynaldi、あなたは大歓迎です。 –

関連する問題