SQL层次结构计数总计报告

时间:2014-12-16 16:18:24

标签: sql sql-server count parent-child hierarchy

我正在使用SQL Server 2012和Report Builder创建一个报告,该报告必须显示每个父元素的高,中,低级别的风险总数。

每个元素包含许多额定等级的风险。我需要父元素的总数。总数将包括所有子元素的数量以及元素本身可能具有的数量。

我在查询中使用CTE - 我附加的代码不起作用(没有错误 - 它只是显示不正确的结果)而且我不确定我的逻辑是否正确?

希望有人可以提供帮助。提前致谢。

我的表结构是:

ElementTable

ElementTableId(PK)ElementName ElementParentId

RiskTable

RiskId(PK)RiskName RiskRating ElementId(FK)

我的查询:

WITH cte_Hierarchy(ElementId, ElementName, Generation, ParentElementId)
     AS (SELECT ElementId,
                NAME,
                0,
                ParentElementId
         FROM   Extract.Element AS FirtGeneration
         WHERE  ParentElementId IS NULL
         UNION ALL
         SELECT NextGeneration.ElementId,
                NextGeneration.NAME,
                Parent.Generation + 1,
                Parent.ElementId
         FROM   Extract.Element AS NextGeneration
                INNER JOIN cte_Hierarchy AS Parent
                        ON NextGeneration.ParentElementId = Parent.ElementId),
     CTE_HighRisk
     AS (SELECT r.ElementId,
                Count(r.RiskId) AS HighRisk
         FROM   Extract.Risk r
         WHERE  r.RiskRating = 'High'
         GROUP  BY r.ElementId),
     CTE_LowRisk
     AS (SELECT r.ElementId,
                Count(r.RiskId) AS LowRisk
         FROM   Extract.Risk r
         WHERE  r.RiskRating = 'Low'
         GROUP  BY r.ElementId),
     CTE_MedRisk
     AS (SELECT r.ElementId,
                Count(r.RiskId) AS MedRisk
         FROM   Extract.Risk r
         WHERE  r.RiskRating = 'Medium'
         GROUP  BY r.ElementId)
SELECT rd.ElementId,
       rd.ElementName,
       rd.ParentElementId,
       Generation,
       HighRisk,
       MedRisk,
       LowRisk
FROM   cte_Hierarchy rd
       LEFT OUTER JOIN CTE_HighRisk h
                    ON rd.ElementId = h.ElementId
       LEFT OUTER JOIN CTE_MedRisk m
                    ON rd.ElementId = m.ElementId
       LEFT OUTER JOIN CTE_LowRisk l
                    ON rd.ElementId = l.ElementId
WHERE  Generation = 1 

编辑:

示例数据

ElementTableId(PK) -- ElementName -- ElementParentId
1 ------------------- Main --------------0
2 --------------------Element1-----------1
3 --------------------Element2 ----------1
4 --------------------SubElement1 -------2

RiskId(PK) RiskName RiskRating ElementId(FK)
a -------- Financial -- High -----  2
b -------- HR --------- High -----  3
c -------- Marketing -- Low ------- 2
d -------- Safety -----Medium ----- 4

示例输出:

Element Name   High   Medium   Low  
Main ---------- 2 ---- 1 -------1

1 个答案:

答案 0 :(得分:0)

这是您的示例表

SELECT * INTO #TABLE1
FROM
(    
    SELECT 1 ElementTableId, 'Main' ElementName ,0 ElementParentId
    UNION ALL
    SELECT 2,'Element1',1
    UNION ALL
    SELECT 3, 'Element2',1
    UNION ALL
    SELECT 4, 'SubElement1',2
)TAB

SELECT * INTO #TABLE2
FROM
(    
    SELECT 'a' RiskId, 'Fincancial' RiskName,'High' RiskRating ,2 ElementId
    UNION ALL
    SELECT 'b','HR','High',3
    UNION ALL
    SELECT 'c', 'Marketing','Low',2
    UNION ALL
    SELECT 'd', 'Safety','Medium',4
)TAB

我们正在寻找父母的子女,其HighMediumLow,并使用cross join向父母展示其子女的所有组合{ {1}},HighMedium

<强>更新

以下变量可用于动态访问记录。

Low

在查询

中使用上述变量
DECLARE @ElementTableId INT;
--SET @ElementTableId = 1

<强> RESULT

enter image description here

更新2

我正按照您的新要求进行更新

以下是我已添加额外数据以进行测试的示例表

;WITH CTE1 AS
(
     SELECT *,0 [LEVEL]  FROM #TABLE1 WHERE ElementTableId = @ElementTableId
     UNION ALL
     SELECT E.*,e2.[LEVEL]+1  FROM #TABLE1 e 
     INNER JOIN CTE1 e2 on e.ElementParentId = e2.ElementTableId
     AND E.ElementTableId<>@ElementTableId
)
,CTE2 AS
(
    SELECT E1.*,E2.*,COUNT(RiskRating) OVER(PARTITION BY RiskRating) CNT 
    from CTE1 E1
    LEFT JOIN #TABLE2 E2 ON E1.ElementTableId=E2.ElementId  
)
,CTE3 AS
(
    SELECT DISTINCT T1.ElementName,C2.RiskRating,C2.CNT  
    FROM #TABLE1  T1
    CROSS JOIN CTE2 C2
    WHERE T1.ElementTableId = @ElementTableId
)
SELECT *
FROM CTE3
PIVOT(MIN(CNT)
      FOR RiskRating IN ([High], [Medium],[Low])) AS PVTTable

我在查询中写了逻辑

SELECT * INTO #ElementTable
FROM
(    
    SELECT 1 ElementTableId, 'Main' ElementName ,0 ElementParentId
    UNION ALL
    SELECT 2,'Element1',1
    UNION ALL
    SELECT 3, 'Element2',1
    UNION ALL
    SELECT 4, 'SubElement1',2
    UNION ALL
    SELECT 5, 'Main 2',0
    UNION ALL
    SELECT 6, 'Element21',5
    UNION ALL
    SELECT 7, 'SubElement21',6
    UNION ALL
    SELECT 8, 'SubElement22',7
    UNION ALL
    SELECT 9, 'SubElement23',7
)TAB

SELECT * INTO #RiskTable
FROM
(    
    SELECT 'a' RiskId, 'Fincancial' RiskName,'High' RiskRating ,2 ElementId
    UNION ALL
    SELECT 'b','HR','High',3
    UNION ALL
    SELECT 'c', 'Marketing','Low',2
    UNION ALL
    SELECT 'd', 'Safety','Medium',4
    UNION ALL
    SELECT 'e' , 'Fincancial' ,'High'  ,5 
    UNION ALL
    SELECT 'f','HR','High',6
    UNION ALL
    SELECT 'g','HR','High',6
    UNION ALL
    SELECT 'h', 'Marketing','Low',7
    UNION ALL
    SELECT 'i', 'Safety','Medium',8
    UNION ALL
    SELECT 'j', 'Safety','High',8
)TAB