SSRS:递归父子

时间:2016-01-20 00:36:15

标签: sql-server recursion reporting-services hierarchy

我想使用这个简单的表在SSRS中创建分层报告? 请你帮助我好吗?我按照这里的教程:https://www.mssqltips.com/sqlservertip/1939/working-with-a-parent-child-hierarchy-in-sql-server-reporting-services-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 个答案:

答案 0 :(得分:2)

这适用于任何深度(假设您没有为SORT_PATH传递VARCHAR(50))。当您沿着层次结构向下构建一个可以按(SORT_PATH)排序的字符串时,可以使用“Trick”。最后,我们可以使用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

答案 1 :(得分: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