【问题标题】:SSRS: Recursive Parent ChildSSRS:递归父子
【发布时间】:2016-01-20 00:36:14
【问题描述】:

我想使用这个简单的表格在 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 分组并且 Recursive Parent 是 COL1 时,我没有得到想要的结果。

这是我的桌子:

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

这是我想要使用 SSRS 获得的结果。喜欢图片的缩进样式..

╔═══════════════╦══╗
║     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

【问题讨论】:

    标签: sql-server recursion reporting-services hierarchy


    【解决方案1】:

    这应该适用于任何深度(假设您没有为 SORT_PATH 传递 VARCHAR(50))。当您沿着层次结构向下移动时,“技巧”会构建一个可以按 (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
    

    【讨论】:

    • 嗯。这个解决方案要简单得多。我没有想到如何像这样排序。我唯一要添加的(如果它对问题很重要的话)是REPLICATE('-', SQUARE(BOMLevel)) 会产生完整的期望输出。
    • 我忘了说我想使用 SSRS 来实现这一点。但我会试试这个。谢谢
    • 是的!我想通了.. 正确的关键是让 SORT_PATH / 键类型来识别哪一行属于哪个父级!
    • 很快就谈到了。只要我的深度超过 2 级,查询就不起作用。
    • 如果我添加这个INSERT INTO @Component ( COL1, COL2 ) VALUES ( 'STLSCH40', 'HELLOTHERE' ) 来创建一个额外的级别(TEST01>TEST04>STLSCH40>HELLOTHERE),它的工作方式与我期望的一样,显示路径为---HELLOTHERE
    【解决方案2】:

    这似乎是一种时髦的方法,但我真的想不出一种以您期望的格式输出结果的好方法:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-27
      • 1970-01-01
      • 1970-01-01
      • 2011-06-05
      • 2017-11-06
      • 2014-05-19
      相关资源
      最近更新 更多