如何设计SSRS条形图

时间:2017-05-05 12:57:50

标签: sql-server reporting-services ssrs-2012

我想创建报告,如下图所示的SSRS报告。

黄色部分表示SET_PHASE, 绿色部分表示PROD_PHASE

Expected

我的查询结果如下:

Query

我想显示每行,所有订单,我想为每个订单显示,SETUP和PRODUCTION取决于duratıon时间。

SET_PHASE的持续时间为SET_DURATION

PROD_PHASE的持续时间为PROD_DURATION

我希望所以我的查询很清楚:)你能帮我解决问题吗?

答案:

Hello Alan,

目前的情况我只有这些数据:

PROD100059335   SETUP   PRODUCTION  1   14  LINE 4
PROD100058991   SETUP   PRODUCTION  1   5   LINE 6
PROD100059259   SETUP   PRODUCTION  2   24  LINE 4
PROD100059188   SETUP   PRODUCTION  1   3   LINE 2
PROD100059248   SETUP   PRODUCTION  1   15  LINE 2
PROD100059055   SETUP   PRODUCTION  2   23  LINE 2
PROD100058754   SETUP   PRODUCTION  5   18  LINE 6

如果我使用您的查询,我只显示“PROD100058754”,“PROD100059259”,“PROD100059055”这些订单。我不明白为什么其他数据会丢失。

直到“DECLARE @n TABLE(n int)”部分我可以显示其他数据。但之后我无法表现出来。

我在SSRS上应用了程序,我的报告显示如下:

enter image description here

我做不到,我不知道如何解决它们:(

例如“PROD100059259”此订单通常具有设置阶段,但在报告中我没有黄色字段。

你对我有什么建议吗?

1 个答案:

答案 0 :(得分:2)

好的,这是尝试给你你想要的东西,但有几点需要注意:

  1. 持续时间已缩放,且任何操作都不会少于1个时段,因此设置与生产持续时间仅为近似值
  2. 我还没有找到标记每个栏的好方法,所以我使用了工具提示
  3. 首先是代码 ...我已经添加了很多评论,所以希望您可以根据您的示例数据进行操作。

    注意:我已经更新了表格,因为现在看来您使用的是整数持续时间,而不是第一个示例中的00:00格式。

    -- CREATE A TEST TABLE AND POPULATE IT
    DECLARE @data TABLE(STR_ORDER_ID varchar(20), SET_DURATION varchar(10), PROD_DURATION varchar(10), Set_decimal int, Prod_Decimal int, Line varchar(10))
    
    INSERT INTO @data
    VALUES
    ('PROD100059335', NULL, NULL, 1, 14, 'LINE 4'),
    ('PROD100058991', NULL, NULL,1, 5, 'LINE 6'),
    ('PROD100059259', NULL, NULL,2, 24, 'LINE 4'),
    ('PROD100059188', NULL, NULL,1, 3, 'LINE 2'),
    ('PROD100059248', NULL, NULL,1, 15, 'LINE 2'),
    ('PROD100059055', NULL, NULL,2, 23, 'LINE 2'),
    ('PROD100058754', NULL, NULL,5, 18, 'LINE 6')
    
    DECLARE @Gap int = 2 -- determines how many columns we use to separate each order
    
    -- ASSUME durations are in hours/minutes or minutes/seconds and convert them to decimal minutes or decimal seconds respectively
    
    -- COMMENTED THIS AS WE NO LONGER NEED IT. No longer required as durations are now integer values.
    --UPDATE d 
    --    SET 
    --        Set_decimal = (CAST(LEFT(d.SET_DURATION, len(d.SET_DURATION)-3) AS INT) * 60) +  CAST(RIGHT(d.SET_DURATION, 2) AS INT)  ,
    --        Prod_Decimal = (CAST(LEFT(d.PROD_DURATION, len(d.PROD_DURATION)-3) AS INT) * 60) +  CAST(RIGHT(d.PROD_DURATION, 2) AS INT) 
    --FROM @data d
    
    
    -- CREATE A NORMALISED TABLE, this will just help to make the next steps simpler
    DECLARE @normData TABLE(RowId INT IDENTITY (1,1), Line varchar(10), STR_ORDER_ID varchar(20), OperationOrder int, Operation varchar(10), Duration int)
    INSERT INTO @normData (Line, STR_ORDER_ID, OperationOrder, Operation, Duration)
    SELECT * FROM (
    SELECT Line, STR_ORDER_ID, 1 as OperationOrder , 'SET' as Operation , Set_decimal FROM @data 
    UNION
    SELECT Line, STR_ORDER_ID, 2 , 'PROD' , Prod_decimal FROM @data 
    UNION
    SELECT Line, STR_ORDER_ID, 3 , 'GAP' , @Gap FROM @data )  u -- this adds dummy data that will act as gaps in hte timeline. Change 5 to whatever value suits you best
        ORDER BY Line, STR_ORDER_ID, OperationOrder
    
    -- find the largest line running total duration per line and scale it to fit to 240 (so we dont go over 256 column limit in SSRS)
    DECLARE @MaxDur INT = (SELECT MAX(rt) FROM (
                            select  *
                                , SUM(Duration) OVER(PARTITION BY Line ORDER BY Line, STR_ORDER_ID, OperationOrder) AS Rt
                             from @normData) mRt)
    
    
    -- Now scale the values back so they fit but don't let any value become less than 1
    IF @MaxDur > 240
        BEGIN
            UPDATE nd 
                SET Duration = CASE WHEN nd.Duration / (@MaxDur/240) <1 THEN 1 ELSE nd.Duration / (@MaxDur/240) END
                FROM @normData nd
        END
    
    /* check what we have so far by uncommenting this bit
    select  *
        , SUM(Duration) OVER(PARTITION BY Line ORDER BY Line, STR_ORDER_ID, OperationOrder) AS Rt
     from @normData
    --*/    
    
    -- ================================================================ --
    -- At this point you 'may' have enough data to plot a bar chart. == --
    -- ================================================================ --
    
    -- CREATE A SIMPLE NUMBERS TABLE, we'll need this to act as our time series
    DECLARE @n TABLE(n int)
    DECLARE @i int  = 0
    DECLARE @t int  = @MaxDur --(SELECT max(Duration) +5 FROM @normData) -- simple loop counter target set to slightly bigger than our highest duration
    WHILE @i<@t
        BEGIN
            INSERT INTO @n SELECT @i
            SET @i = @i +1
        END
    
    -- Join our numbers table to our real data
    -- This will give us at least 1 row per time slot and associated activity during that time slot.
    -- We can plot this driectly as a matrix.
    SELECT * 
        FROM @n n
            LEFT JOIN ( 
                    -- Sub queries below give use a runnintg total, we then join this back to itself to get the previous 
                    -- running total and this will give us the 'time range' for each operation.
                    SELECT 
                        a.*
                        , ISNULL(b.Rt,0)+1 AS TimeStart
                        , a.RT AS TimeEnd
                        FROM
                        (SELECT *
                                , SUM(Duration) OVER(PARTITION BY Line ORDER BY Line, STR_ORDER_ID, OperationOrder) AS Rt
                             from @normData
                        ) a
                    LEFT JOIN 
                        (SELECT *
                                , SUM(Duration) OVER(PARTITION BY Line ORDER BY Line, STR_ORDER_ID, OperationOrder) AS Rt
                             from @normData
                        ) b
                        ON a.RowId = b.RowId + 1 and a.Line = b.Line 
                    ) d
                ON n.n between d.TimeStart and d.TimeEnd
        ORDER BY Line, STR_ORDER_ID, OperationOrder, n, TimeStart, TimeEnd
    

    您可以在数据集中使用上述代码。

    报告设计: 报告很简单。它是一个基于Line的单行组和基于n的单个列组的矩阵,这是我们的时段编号。

    我添加了一个空白行作为&#39;栏之间的间隔符。

    enter image description here

    细胞背景的表达是

    =SWITCH(
    Fields!OperationOrder.Value = 1, "Yellow",
    Fields!OperationOrder.Value = 2, "Green",
    Fields!OperationOrder.Value = 3, Nothing,
    True, Nothing
    )
    

    还有一个显示STR_ORDER_ID和操作名称的工具提示。

    您将获得以下输出。

    enter image description here