I have looked a lot of places to see if this is possible, but so far come up empty.
What I am trying to do is make the Y axis of a line chart based on the largest value and smallest value in the X axis. I've thought of how best to ask this, I am simplifying here. There's more to what I am doing but this is the part I can't figure out.
Click to view example: Set Y Axis to X Axis Values
Here is a small sample of the dataset. it's very basic.
https://1drv.ms/x/s!AsF_vHid6sbi30XMcIVeA5vqItsF?e=9CmOZk
There is no series group, and the category group is based on week beginning value. The calculation is the sum of referral counts.
I did try writing expression to reference the MAX(SUM(Fields!RefCount.Value, "CategoryGroupName")) and various other similar expressions, but since it is out of the scope of the Y axis, it won't work.
Thanks for any help or advice.
I created a random set of data, it changes each time you run the report so good for testing. It adds 50 to all the values so we know we will never get a zero (for testing).
I used the following dataset query
DECLARE #t TABLE (ReferralWeek date, RefCnt int)
INSERT INTO #t VALUES
('2020-06-21', 50+(rand()*500)), ('2020-06-21', 50+(rand()*500)), ('2020-06-07', 50+(rand()*500)), ('2020-06-07', 50+(rand()*500)), ('2020-03-29', 50+(rand()*500)),
('2020-06-21', 50+(rand()*500)), ('2020-05-03', 50+(rand()*500)), ('2020-05-24', 50+(rand()*500)), ('2020-06-14', 50+(rand()*500)), ('2020-04-12', 50+(rand()*500)),
('2020-04-19', 50+(rand()*500)), ('2020-04-12', 50+(rand()*500)), ('2020-06-21', 50+(rand()*500)), ('2020-04-26', 50+(rand()*500)), ('2020-06-21', 50+(rand()*500)),
('2020-04-19', 50+(rand()*500)), ('2020-06-07', 50+(rand()*500)), ('2020-05-10', 50+(rand()*500)), ('2020-06-21', 50+(rand()*500)), ('2020-05-10', 50+(rand()*500)),
('2020-05-31', 50+(rand()*500)), ('2020-06-14', 50+(rand()*500)), ('2020-05-17', 50+(rand()*500)), ('2020-04-12', 50+(rand()*500)), ('2020-04-26', 50+(rand()*500)),
('2020-05-03', 50+(rand()*500))
SELECT * FROM #t
I then created a new report, added line chart, set values to SUM(RefCnt) and Category Group to ReferralWeek.
Next I right-clicked the Category Group and chose "properties" from here I could see the name was "Chart1_CategoryGroup". This is the scope expression we will need to calculate the vertical axis range.
Next I right-click the vertical axis and chose "properties".
I set the interval type to "number" and then set the expressions for the min and max values to the following...
=MIN(SUM(Fields!RefCnt.Value, "Chart1_CategoryGroup"))
and
=MAX(SUM(Fields!RefCnt.Value, "Chart1_CategoryGroup"))
Note we used the category group name as the scope name.
This gets us part of the way but the interval has to be calculated too or the highest number wont; be show on the axis, so if he highest number was 605 then the axis might show 600 with the last point slightly above it.
We can fix this by calculating the interval. It might not 100% with this simple example but should be close enough.
The interval was set to the following expression.
=(
MAX(SUM(Fields!RefCnt.Value, "Chart1_CategoryGroup"))
-
MAX(SUM(Fields!RefCnt.Value, "Chart1_CategoryGroup"))
)
/ 10
You can adjust how many labels you want by adjusting the '10' divisor.
This gives us the following
BEWARE!
By using the smooth line chart and depending on the data, your curve may now fall off the bottom of the chart. Within your requirements, there is nothing you can do other than add some padding to the minimum value or switch to a non-smoothed chart.
Here's an example of what you might get. (the beauty of a random number generator for testing ! )
Related
I need to create a SSRS report to present actual start date vs. planned start dates for milestones of a project (selected as input parameter)
The chart should look like this:
I have created the table in a separate table. However, I don’t know which chart type should I use and how do I have to set up the chart? (Chart Data, Category Groups and Series Groups).
(Data comes from SQL Server, SSRS Version 14.0.1016.285; SSDT 15.6.4)
Many Thanks in advance
This might look a bit long winded but it's fairly simple so stick with it :)
To start with I did not know your data structure so I've just made some assumptions. You may have to rework some of this to get it to fit but I've tried to keep it simple.
The approach will be to use a subreport to plot the dots and a main report to show the overall table. With this in mind, as we will have more than one dataset referencing our data I added some tables to my sample database before I started wit the following.
The first is a simple table containing months and years, you could a use view over a date table if you have one but this will do for now.
CREATE TABLE prjYearMonth (Year int, Month int)
INSERT INTO prjYearMonth VALUES
(2018, 8),
(2018, 9),
(2018, 10),
(2018, 11),
(2018, 12),
(2019, 1),
(2019, 2)
Next is the project milestone table
CREATE TABLE prjMileStones (msID int, msLabel varchar(50), msPlannedStart date, msActualStart date)
INSERT INTO prjMileStones VALUES
(1, 'Milestone 1', '2018-10-30', '2018-12-13'),
(2, 'Milestone 2', '2018-11-12', '2018-12-10'),
(3, 'Milestone 3', '2018-10-21', '2018-12-25'),
(4, 'Milestone 4', '2018-10-18', '2018-11-28'),
(5, 'Milestone 6', '2019-01-08', '2019-01-29')
OK, Now let's start the report...
Create a new empty report then add a dataset with the following query
SELECT
*
FROM prjYearMonth d
LEFT JOIN prjMileStones t on (d.Year = YEAR(t.msPlannedStart) AND d.Month = Month(t.msPlannedStart))
or (d.Year = YEAR(t.msActualStart) AND d.Month = Month(t.msActualStart))
Now add a matrix item to the report. Add a Row Group that groups on msLabel.
Next add two Column Groups. First a group that groups on Month and then add a parent group that groups on Year.
Add columns on the row group so that you end up with 4 columns msID; msLabel; msPlannedStart; msActualStart.
Finally (for now) set the Expression of the Month field (the one in the column header) to be
= Format(DATESERIAL(2017, Fields!Month.Value, 1), "MMM")
This will just give us the month name rather than the number (the 2017 is irrelevant, any year will do). Now just format as required.
You report design should look something like this..
If we run the report now we will get this..
Now to plot the dots...
For this we will create a small subreport. The subreport will accept 3 parameters. Year, Month, msID (the milestone ID from your main table). We will need the data in a slightly different structure for this sub report but the work can be done in the dataset query so nothing new is required in the database itself.
So, create a new report, let's call it _subMonthChart.
Next add a dataset with the following query..
DECLARE #t TABLE(msID int, msLabel varchar(50), PlannedOrActual varchar(1), msStartDate date)
INSERT INTO #t
SELECT msId, mslabel, 'P', msPlannedStart FROM prjMileStones
UNION ALL
SELECT msId, mslabel, 'A', msActualStart FROM prjMileStones
SELECT
1 AS Y, Day(msStartDate) as Day, PlannedOrActual
FROM prjYearMonth d
LEFT JOIN #t t on (d.Year = YEAR(t.msStartDate) AND d.Month = Month(t.msStartDate))
WHERE [Year] = #Year and [Month] = #Month and msID = #msID
Your report should now have 3 parameters that were automatically created, edit all three to Allow Nulls.
Note: The Y in the dataset is just some arbitrary value to help plot on the chart,. I will set the Y axis to range from 0 - 2 so 1 will sit in the middle.
Next, add a line chart with markers. Don't worry about the size for now...
Set the Values as Y
Set the Category Groups as Day
Set the Series Groups as PlannedOrActual
Right click the horizontal Axis, choose properties and set the Axis Type to Scalar, switch off 'Always include zero' then set Min = 1, Max = 31, Interval = 1, Interval Type = Default.
Note that for data in months that don't have 31 days the plots points will not be accurate but they will be close enough for your purposes.
Right click the Vertical Axis, choose properties and set the Mn=0, Max=2, Interval = 1, Interval Type = Default
Next, right click on one of the series lines and choose properties. Set the marker to Diamond, the marker size to 8pt and the Marker Color this expression =IIF(Fields!PlannedOrActual.Value = "P", "Blue", "Green")
The report design should look something like this... (check the highlighted bits in particular)
Now let's quickly test the subreport, based on my sample data I set the parameters to 2019, 1 and 5 and get the following results....
As we can see, our two dates that fall in January for this milestone were plotted in roughly the correct positions.
Nearly there...
Next right click on both Axes and turn off 'Show Axis' so we hide them.
Now resize the chart to something that will fit in the main report cell. In my example I set the size to 2cm, 1.2cm and moved it top left of the report. Then set the report to be the same size as the chart (2cm,1.2cm again in my case).
Save the sub report and go back to your main report...
For the 'Data' cell where the rows and columns intersect, set the size to match the subreport size (2cm, 1.2cm) then right click the cell and insert subreport.
Right click the newly inserted subreport item and choose properties.
Choose _subMonthChart as the subreport from the dropdown.
Click the parameters tab. Add an entry for each parameter (Year/Month/msID) and set its value to be the corresponding field from the dataset.
FINALLY !!!! Set the border on the cell containing the subreport to have borders all round, just so it matches your mock-up..
Your report design should now look like this...
Now when the report runs, it will pass in the month, year and milestone ID to the subreport in each cell which in turn will plot the dates as required.
When we run the report we should finally get this...
This may need some refining but hopefully you can get this going based on this. If you have trouble I suggest you recreate this example in its entirety, get it working and then swap out the database parts to fit your current database.
i need to create parameter list of months and then (after select) recalculate two others paramateres in date format ([first day] and [last day]) of this month, can you please help me?
You are querying a database server to generate the list of months, although there's no need to do that. I suggest to rather create a list of months in the report and let the report calculate the month's names, so the language depends on the Language setting of the report (which can be the language configured in the user's browser).
For example, to calculate the Label for the Value 1, use an expression like =MonthName(1).
The Parameters FirstDay and LastDay (or just the values whenever you need them) can be calculated using these expressions:
FirstDay: =DateSerial(Today.Year, Parameters!Month.Value, 1)
LastDay: =DateSerial(Today.Year, Parameters!Month.Value, 1).AddMonths(1).AddDays(-1)
I have a query that gives me the daily status of an item based on desired date range (parameters). This status will vary and can repeat. For example, it can chronologically be: Operational, Repair, Inspection, Operational, Inspection. As you can see Operational & Inspection are represented twice but at different times. While this is true, I cannot seem to get this represented graphically in a Range Bar Chart because it will only display one instance of each status (as shown in the picture). The picture indicates where the remaining status should be presented.
Range bar Chart Error
The data set I am working with is as follows:
Range bar Chart Error Data
As you can see, the chart should represent 4 status in the following order: Inspection, Operational, Repair, Operational but does not display the 2nd Operational status.
Can anyone assist me to overcome this particular hurdle or is this not possible?
This should point you in the right direction... This is how I would probably approach it.
You need to add an additional column to your dataset. I replicated your dataset into a table variable and then used the following to get the additional column
-- this just replicates your data..
DECLARE #t TABLE(StatusDate DATE, StatType varchar(20), statStart DateTime, statEnd DateTime, StatusDays int)
INSERT INTO #t VALUES
('2017-02-16', 'Inspection', '2017-01-30 12:49:14', '2017-02-21 12:49:14', 22),
...
...
('2017-03-14', 'Operational', '2017-03-01 11:49:11', '2017-04-19 15:19:48', 49)
-- the important bit
SELECT
*
, DENSE_RANK() OVER(ORDER BY statStart) as Sort
FROM #t
This gives us the following output.
We can use this extra field in SSRS to group and sort the data correctly.
I then used the following expression for the chart series color property to make sure that the colours are consistent with the statType
=SWITCH(
Fields!StatType.Value = "Inspection", "Tan",
Fields!StatType.Value = "Operational", "Green",
Fields!StatType.Value = "Repair", "Red",
True, "Blue"
)
(the Blue line is there in case we are missing a type, it'll show on the chart n blue.)
This gives us..
Hopefully that will give you enough to go on.
Trying to recreate this formula in Pentaho Mondrian Cube.
iif(ISLEAF([Time].[Month].CurrentMember)),[Measures].m1,0)
This formula is being used in SSAS cube already. Need to recreate similar formula in Pentaho Mondrian Cube.
Can IsLeaf be used in mondrian or is there any alternative for this?
Something like the following should work at any arbitrary level within the default hierarchy.
It will return [Mesures].m1 for the last year, which (has non-empty m1 measure and satisfies your filter conditions) in case you select [Time].[Year] members.
Or it will return the measure for the last month of the last year, which has non-empty m1 measure in case you select [Time].[Month] members.
Though I don't think it will work if you mix members for different levels (e.g. WITH SET time_members AS {[Time].[2017], [Time].[2017].[1]. [Time].[2017].[1].[31]})
If you don't need such a generic approach, then this solution may be simplified and the measure calculation speed may be improved.
Warning: the query may cause 100% CPU utilization (or may not, I am not sure), thus making your server unresponsive. So, choose your testing environment carefully.
Disclaimer: I don't have mondrian to test at the moment, so the following example is very likely to have errors.
Iif(
// Check if current [Time] member is the last member:
[Time].CurrentMember
IS
// Take the 0th member from the end of the set (AFAIK, mondrian sets are guaranteed to be ordered):
Tail(
// AFAIK, Level.Members returns the full set of members, disregarding query filters.
// So I use Filter function to filter members, which don't exist in context of current cell.
// It should leave only members, which (are related to current cell and satisfy filter conditions of the query).
Filter(
[Time].CurrentMember.Level.members
// If your measure is nullable, then you might want to use count measure in this condition instead of m1:
, NOT IsEmpty([Measures].m1)
)
// Number of members to get by the Tail() function:
, 1
// Return the only member of the set as a Member (not as a Set):
).Item(0)
// return if true
, [Measures].m1
// else:
, 0
)
Some points that may be problematic and need to be tested:
How the measure is calculated if the last [Time] member has empty m1
measure (if this is a valid case for your measure)
How the measure is calculated at different levels of [Time]
hierarchy.
How the measure is calculated if you don't use [Time] dimension in
report explicitly.
How the measure is calculated if you use [Time] dimension on slicer
axis only (in WHERE condition)
How the measure is calculated if you use restricted set of [Time]
members, e.g. explicitly enumerating members in set literal (e.g.
{[Time].[2006].[01], [Time].[2006].[02]}) or via using Filter()
function on the dimension.
How the measure is calculated if you use fiters on other
dimensions/measures.
How the measure is calculated at calculated members of [Time]
dimension (including totals and sub-totals generated by Analyzer).
How the measure is calculated if you select members from different
levels on the same axis.
I have a chart with these characteristics:
chart type is XY (scatter )
all XY data have x-values that are integers; they are called "Update Cycle" numbers. This represents "score" data from a given program.
in addition to the values that produce the XY data, I've added two other elements to the "Values:" list: one that is the average of the XY data for any Update Cycle (x-axis) value, and another that is the average of "similar programs" for any Update Cycle. These elements are plotted as lines ("trend lines") on the chart.
Category Group is Update Cycle number
Series Group are (1) PersonID and (2) ProgramID
It all plots fine, but here's my problem:
If I add a Legend, it wants to add Legend entries for each and every point for each and every person (because of SeriesGroup1) - I imagine it's also showing legend entries for the second series, but there are so many for the first series, I can't read anything.
Question: How do I supress legend entries for the first series and only display the two legend entries for the 2nd series?
I have the same problem, Is any solutions for the series text overlaping?, I found a solutions, but I cann't use, because divided the chart in various charts, by the way, heres is the link of the article:
http://social.msdn.microsoft.com/Forums/en-US/sqlreportingservices/thread/841e1515-3519-4c4f-a76f-f6fcebd25dfd/
If somebody have another solutions, pleace post it.
Thanks and sorry, my English is a little poor.