2016-01-20 79 views
1

我想使用这个简单的表在SSRS中创建分层报告? 你能帮我吗?我按照这里的教程:https://www.mssqltips.com/sqlservertip/1939/working-with-a-parent-child-hierarchy-in-sql-server-reporting-services-ssrs/SSRS:递归父子

但我无法弄清楚EmployeeKey和ParentEmployeeKey如何适用于我的表。至于我的表关注Col2是员工和Col1是父母。但是在SSRS中,当我通过Col2分组并且递归父母是COL1时,我没有得到期望的结果。

这里是我的表:

╔══════════════╦══════════════╗ 
║  COL1  ║  COL2  ║ 
╠══════════════╬══════════════╣ 
║ TEST01  ║ TEST02  ║ 
║ TEST01  ║ TEST03  ║ 
║ TEST01  ║ TEST04  ║ 
║ TEST02  ║ LAB   ║ 
║ TEST02  ║ STL40  ║ 
║ TEST03  ║ LABSTL  ║ 
║ TEST03  ║ STLSCH40  ║ 
║ TEST04  ║ LABSTL  ║ 
║ TEST04  ║ FLG41  ║ 
║ TEST04  ║ STLSCH40  ║ 
╚══════════════╩══════════════╝ 

这是我想用SSRS获得的结果。像图片中的缩进风格.. enter image description here

╔═══════════════╦══╗ 
║  COL1  ║ ║ 
╠═══════════════╬══╣ 
║ TEST01  ║ ║ 
║ -TEST02  ║ ║ 
║ ----LAB  ║ ║ 
║ ----STL40  ║ ║ 
║ -TEST03  ║ ║ 
║ ----LABSTL ║ ║ 
║ ----STLSCH40 ║ ║ 
║ -TEST04  ║ ║ 
║ ----LABSTL ║ ║ 
║ ----FLG41  ║ ║ 
║ ----STLSCH40 ║ ║ 
╚═══════════════╩══╝ 

我不知道得到上述的缩进风格的结果。我是否需要使用HierarchyID和IsDescendantOf或递归CTE。 这是我做的递归CTE和它的结果。

Declare @Col1 varchar(30)='TEST01'; 
Declare @BomLevel Integer=0; 
WITH tBOM 
AS 
(
select a.Col1 , a.Col2, @BomLevel "BOMLevel" from Component A 
WHERE Col1= @Col1 
UNION ALL 
Select c.Col1, c.Col2, BomLevel+1 From Component C 
INNER JOIN tBOM on tBOM.Col2=c.Col1 
) 
select Col1,Col2 ,BOMLevel from tbom 


Col1        Col2       BOMLevel 
TEST01      TEST02       0 
TEST01      TEST03       0 
TEST01      TEST04       0 
TEST02      STL40       1 
TEST02      LAB        1 
TEST03      STLSCH40      1 
TEST03      LABSTL       1 
TEST04      STLSCH40      1 
TEST04      FLG41       1 
TEST04      LABSTL       1 

回答

2

这应该适用于任何深度你不通过VARCHAR(50)SORT_PATH)。当您沿着层次结构创建一个可以排序的字符串(SORT_PATH)时,“技巧”。最后,我们可以使用REPLICATE()和我们的BOMLevel缩进某些东西(在本例中为连字符)。

SET NOCOUNT ON; 

DECLARE @Component AS TABLE (
     COL1 VARCHAR(50) , 
     COL2 VARCHAR(50) 
     ); 

INSERT INTO @Component 
     (COL1, COL2) 
VALUES (NULL,  'TEST01'), -- ADDED 
     ('TEST01', 'TEST02'), 
     ('TEST01', 'TEST03'), 
     ('TEST01', 'TEST04'), 
     ('TEST02', 'LAB' ), 
     ('TEST02', 'STL40' ), 
     ('TEST03', 'LABSTL'), 
     ('TEST03', 'STLSCH40'), 
     ('TEST04', 'LABSTL'), 
     ('TEST04', 'FLG41' ), 
     ('TEST04', 'STLSCH40') 

; 
WITH tBOM 
      AS (SELECT A.COL1 , -- PARENT 
         A.COL2 , -- CURRENT 
         0 AS "BOMLevel", 
         CAST(A.COL2 AS VARCHAR(50)) AS SORT_PATH 
       FROM  @Component A 
       WHERE A.COL1 IS NULL 
       UNION ALL 
       SELECT C.COL1 , 
         C.COL2 , 
         BOMLevel + 1, 
         CAST(SORT_PATH + '.' + C.COL2 AS VARCHAR(50)) AS SORT_PATH 
       FROM  @Component C 
         INNER JOIN tBOM ON tBOM.COL2 = C.COL1 
      ) 
    SELECT COL1 , 
      COL2 , 
      BOMLevel, 
      SORT_PATH, 
      REPLICATE('-', tBOM.BOMLevel) + COL2 AS DISPLAY_PATH 
    FROM tBOM 
    ORDER BY SORT_PATH 
+0

嗯。这个解决方案简单得多。我没有想到如何排序。只有我添加的东西(如果它对问题更重要)是'REPLICATE(' - ',SQUARE(BOMLevel))'会产生完整的所需输出。 – ZLK

+0

我忘了说我想用SSRS来达到这个目的。但我会试试这个。谢谢 – BobNoobGuy

+0

是的!我想清楚了。更正关键是让那个SORT_PATH /键类型来标识哪一行属于哪个父母! – BobNoobGuy

0

这似乎是一种时髦的方式做到这一点,但我真的不能想到一个好办法,在输出格式的结果你期待:

CREATE TABLE #table (Col1 NVARCHAR(100), Col2 NVARCHAR(100)) 
INSERT #table VALUES ('TEST01', 'TEST02') 
, ('TEST01', 'TEST03') 
, ('TEST01', 'TEST04') 
, ('TEST02', 'LAB') 
, ('TEST02', 'STL40') 
, ('TEST03', 'LABSTL') 
, ('TEST03', 'STLSCH40') 
, ('TEST04', 'LABSTL') 
, ('TEST04', 'FLG41') 
, ('TEST04', 'STLSCH40'); 

WITH CTE1 AS (
    SELECT C1.Col1 C1 
     , C2.Col2 C2 
     , C3.Col2 C3 
     , ROW_NUMBER() OVER (ORDER BY C1.Col1, C2.Col2, C3.Col2) RN 
    FROM (SELECT Col1 FROM #table WHERE Col1 NOT IN (SELECT Col2 FROM #table)) C1 
    LEFT JOIN #table C2 ON C2.Col1 = C1.Col1 
    LEFT JOIN #table C3 ON C3.Col1 = C2.Col2 
    GROUP BY C1.Col1, C2.Col2, C3.Col2) 
, CTE2 AS (
    SELECT CASE WHEN RN = 1 THEN C1 ELSE NULL END C1 
    , CASE WHEN RN = 1 THEN CAST('-' + C2 AS NVARCHAR(100)) 
     WHEN (SELECT C2 FROM CTE1 WHERE RN = C.RN-1) = C2 THEN NULL 
     ELSE CAST('-' + C2 AS NVARCHAR(100)) END C2 
    , CASE WHEN RN = 1 THEN CAST('----' + C3 AS NVARCHAR(100)) 
     WHEN (SELECT C3 FROM CTE1 WHERE RN = C.RN-1) = C3 THEN NULL 
     ELSE CAST('----' + C3 AS NVARCHAR(100)) END C3 
    FROM CTE1 C) 
SELECT Col1 
FROM CTE2 
UNPIVOT (Col1 FOR Col IN (C1, C2, C3)) a 

DROP TABLE #table 

该输出:

+--------------+ 
|  Col1  | 
+--------------+ 
| TEST01  | 
| -TEST02  | 
| ----LAB  | 
| ----STL40 | 
| -TEST03  | 
| ----LABSTL | 
| ----STLSCH40 | 
| -TEST04  | 
| ----FLG41 | 
| ----LABSTL | 
| ----STLSCH40 | 
+--------------+ 

......但它假定任何父母的最大深度是2(根据示例)。如果你比这更深入,你不确定它有多深,那么你需要使用动态SQL来产生类似的结果。值得注意的是,如果您想了解如何生成一个HTML列表作为父/子表格的输出,我已经在下面的链接中回答了类似的问题:https://stackoverflow.com/a/34445701/5552667