SQL层次结构计数总计报告

SQL层次结构计数总计报告,sql,sql-server,count,parent-child,hierarchy,Sql,Sql Server,Count,Parent Child,Hierarchy,我正在使用SQL server 2012和报表生成器创建一个报表,该报表必须显示每个父元素在高、中、低级别的风险总数 每个要素都包含一定等级的风险。我需要父元素的总数。总数将包括所有子元素的数量以及元素本身可能拥有的数量 我在我的查询中使用了CTEs-我附加的代码不起作用-没有错误-它只是显示了不正确的结果,我不确定我的逻辑是否正确 希望有人能帮忙。提前谢谢 我的表格结构是: 元素表 ElementTableIdPK ElementName ElementParentId 风险表 风险IDPK风

我正在使用SQL server 2012和报表生成器创建一个报表,该报表必须显示每个父元素在高、中、低级别的风险总数

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

我在我的查询中使用了CTEs-我附加的代码不起作用-没有错误-它只是显示了不正确的结果,我不确定我的逻辑是否正确

希望有人能帮忙。提前谢谢

我的表格结构是:

元素表

ElementTableIdPK ElementName ElementParentId

风险表

风险IDPK风险名称风险评级元素IDPK

我的问题是:

编辑:

样本数据

样本输出:

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

这是你们的样品表

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
我们正在查找父级的子级,其高、中、低计数,并使用交叉联接来显示父级及其子级的高、中、低的所有组合

更新

下面的变量可用于动态访问记录

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

;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
我已在查询中编写了逻辑

;WITH CTE1 AS
(
     -- Here you will find the level of every elements in the table
     SELECT *,0 [LEVEL] 
     FROM #ElementTable WHERE ElementParentId = 0
     UNION ALL
     SELECT ET.*,CTE1.[LEVEL]+1 
     FROM #ElementTable ET 
     INNER JOIN CTE1 on ET.ElementParentId = CTE1.ElementTableId  
)
,CTE2 AS
(
    -- Filters the level and find the major parant of each child
    -- ie, 100->150->200, here the main parent of 200 is 100 
    SELECT *,CTE1.ElementTableId MajorParentID,CTE1.ElementName MajorParentName  
    FROM CTE1 WHERE [LEVEL]=1
    UNION ALL
    SELECT CTE1.*,CTE2.MajorParentID,CTE2.MajorParentName  
    FROM CTE1  
    INNER JOIN CTE2 on CTE1.ElementParentId = CTE2.ElementTableId
)
,CTE3 AS
(
    -- Since each child have columns for main parent id and name, 
    -- you will get the count of each element corresponding to the level you have selected directly
    SELECT DISTINCT CTE2.MajorParentName,RT.RiskRating ,
    COUNT(RiskRating) OVER(PARTITION BY MajorParentID,RiskRating) CNT 
    FROM CTE2 
    JOIN #RiskTable RT ON CTE2.ElementTableId=RT.ElementId  
)
SELECT MajorParentName, ISNULL([High],0)[High], ISNULL([Medium],0)[Medium],ISNULL([Low],0)[Low]
FROM CTE3
PIVOT(MIN(CNT)
      FOR RiskRating IN ([High], [Medium],[Low])) AS PVTTable

你说你的代码不工作是什么意思?您是否收到错误?@TabAlleman查询显示的结果不正确-没有错误消息它显示的结果是什么,与您想要的结果有何不同?@TabAlleman它没有显示每个父项及其子项的总数。它只显示家长本身的总数-不包括所有孩子的结果添加样本数据和所需的outputHi@sarah avanavu感谢您的帮助。这看起来很棒。但是,如果不包括WHERE语句ReviewId=1,我如何得到相同的结果呢。。我想包含的唯一一种WHERE语句是说明这些元素的层次结构的生成/级别的语句,我没有理解。你能提供更新要求的样本数据吗@切斯特纽特,这里的审稿人在哪里@我已经修改了查询。请随意要求任何更改@Chesternutt抱歉,Sarath,我是指ElementTableId!!报告需要是动态的,所以我不想输入ElementTableId,因为这是一个内部值。我需要输入我想要查看其总数的级别/世代
;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
;WITH CTE1 AS
(
     -- Here you will find the level of every elements in the table
     SELECT *,0 [LEVEL] 
     FROM #ElementTable WHERE ElementParentId = 0
     UNION ALL
     SELECT ET.*,CTE1.[LEVEL]+1 
     FROM #ElementTable ET 
     INNER JOIN CTE1 on ET.ElementParentId = CTE1.ElementTableId  
)
,CTE2 AS
(
    -- Filters the level and find the major parant of each child
    -- ie, 100->150->200, here the main parent of 200 is 100 
    SELECT *,CTE1.ElementTableId MajorParentID,CTE1.ElementName MajorParentName  
    FROM CTE1 WHERE [LEVEL]=1
    UNION ALL
    SELECT CTE1.*,CTE2.MajorParentID,CTE2.MajorParentName  
    FROM CTE1  
    INNER JOIN CTE2 on CTE1.ElementParentId = CTE2.ElementTableId
)
,CTE3 AS
(
    -- Since each child have columns for main parent id and name, 
    -- you will get the count of each element corresponding to the level you have selected directly
    SELECT DISTINCT CTE2.MajorParentName,RT.RiskRating ,
    COUNT(RiskRating) OVER(PARTITION BY MajorParentID,RiskRating) CNT 
    FROM CTE2 
    JOIN #RiskTable RT ON CTE2.ElementTableId=RT.ElementId  
)
SELECT MajorParentName, ISNULL([High],0)[High], ISNULL([Medium],0)[Medium],ISNULL([Low],0)[Low]
FROM CTE3
PIVOT(MIN(CNT)
      FOR RiskRating IN ([High], [Medium],[Low])) AS PVTTable