问题
I want to create reports like below picture's report on SSRS.
Yellow parts mean SET_PHASE
,
Green parts mean PROD_PHASE
And my query result like this:
I want to show for per line, all order and I want to show for per order, SETUP and PRODUCTION depends on duratıon time.
SET_PHASE
's duration time is SET_DURATION
,
PROD_PHASE
's duration time is PROD_DURATION
I hope so my query is clear :) Could you help me about issue?
Answer:
Hello Alan,
Current situation I have just these data:
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
And If I use your query I just show "PROD100058754", "PROD100059259", "PROD100059055" these order. I don't understand why other data lost.
until "DECLARE @n TABLE(n int)" part I can show other data. but after that I can not show.
And I applied procedure on SSRS my report shows like this:
I couldn't do correctly and I don't know how can I fix them:(
for example "PROD100059259" this order normally has setup phase but on the report I don't have yellow field.
Do you have any suggestions for me?
回答1:
OK, here is an attempt to give you what you want but there are a few caveats:
- The durations are scaled and no operation can take less than 1 time slot so the setup vs production duration is only approximate
- I haven't found a good way of labelling each bar so I've used tooltips
First the code... I've added lots of comments so hopefully you can follow it thru, it's based on your sample data.
NOTE: I've update the table as it now seems like you are using integer durations rather than the 00:00 format from your first example.
-- 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
You can use the code above in your dataset.
The report design:
The report is very simple. It's a matrix with a single row group based on Line
and a single column group based on n
which is our time slot number.
I've added a blank row to act as a spacer between the 'bars'.
The expression of the cell background is
=SWITCH(
Fields!OperationOrder.Value = 1, "Yellow",
Fields!OperationOrder.Value = 2, "Green",
Fields!OperationOrder.Value = 3, Nothing,
True, Nothing
)
There is also a tooltip which displays STR_ORDER_ID and the operation name.
You get the following output.
来源:https://stackoverflow.com/questions/43805603/how-to-design-bar-chart-on-ssrs