I have a dataset which looks like this
ProjectName MonthsThisYear CompletionDate
ProjectA 5 5/1/2013
ProjectB 7 7/15/2013
ProjectC 10 10/21/2013
I want to bar plot a graph where Y axis is project Name and X axis is January 2013, February 2013 ... December 2013.
Now the bar against projectA must be 5 units long, ProjectB is 7 units long and the bar for Project C should be 10 units long.
so that people can see that ProjectA is completed in May, ProjectB is completed in July and project C in October.
How can I plot this graph?
currently I can plot this correctly... but the X-Asix has 0, 2, 4, 6, 8, 10, 12 on it rather than month names.
I am on SSRS 2008 R2.
This is what I see right now
I just want to see month names and year on X axis.
Maybe some more question detail would be useful, but here's one way that works with your data:
The main issue we're facing is that typically a date is the category, but in this case it's actually the Data value, which gives us less control over the labels compared to a category group.
First, set up a chart with a Category Group based on ProjectName, and a Data expression like:
=DateSerial(Year(Fields!CompletionDate.Value), Month(Fields!CompletionDate.Value), 1)
i.e. the first of the month of each CompletionDate value, otherwise your bars will be between months.
Next, we need to sort out the X axis:
In my example I set Minimum to:
=DateAdd(DateInterval.Month
, -1
, DateSerial(Year(Min(Fields!CompletionDate.Value)), 1, 1))
i.e. December for the last year. Set Maximum to:
=DateSerial(Year(Max(Fields!CompletionDate.Value)), 12, 31)
i.e. the end of the year.
Set Interval to 1 and Interval Type to Months.
Format the X Axis to MMM yyyy.
Looks OK:
If you can actually add a Year column with a value 2013 or whatever, pretty much all of the expressions above can be simplified. For example, I've ignored MonthsThisYear, but if you have a Year column you can build the start of the month value based on MonthsThisYear and Year.
Related
Using SSRS 2016 and SQL 2017 Report Builder
I have a dataset like the following. It has event dates and attendance:
Event_Date Attendance
1/1/2016 1
2/1/2016 2
3/1/2016 3
4/1/2016 4
5/1/2016 5
6/1/2016 6
7/1/2016 7
8/1/2016 8
9/1/2016 9
10/1/2016 10
11/1/2016 11
12/1/2016 12
1/1/2017 5
2/1/2017 6
3/1/2017 7
4/1/2017 8
5/1/2017 9
6/1/2017 10
7/1/2017 11
8/1/2017 12
9/1/2017 13
10/1/2017 14
11/1/2017 15
12/1/2017 16
I am attempting to create a line chart in an SSRS report where there is a datapoint (Attendance) for each element in the series. I am specifying two series -- Series 1 is the attendance for 2016 and Series 2 is the attendance for 2017. Each series will be on a separate line in the chart. The purpose is to visually compare attendance in 2016 vs 2017.
The date periods are determined dynamically by report parameters when the report is run for one series and by variables calculated from the report parameters for the other series.
In the line chart I have defined:
Values are Attendance
Category Groups are Event_Date (with a filter to select events in 2017)
Series Groups are Event_Date (with a filter to select events in 2016)
PROBLEM
When I run the report, the graph renders but has no data (lines).
If I remove the Series Group (events in 2016), the graph renders correctly with only the data line for 2017.
I've been working on this for quite a while and I am stalled trying to figure out what is going on.
Does anyone have any ideas as to why both series are not being graphed and how to fix it?
Many Thanks!
Note: The solution is simple, don't be put off by the length of the reply ! :)
You'll need to make a few simple changes to your dataset query..
Here's a sample query I used to replicate you data.
DECLARE #t TABLE (Event_Date date, Attendance int)
INSERT INTO #t
VALUES
('1/1/2016', 1),
('2/1/2016', 2),
('3/1/2016', 3),
('4/1/2016', 4),
('5/1/2016', 5),
('6/1/2016', 6),
('7/1/2016', 7),
('8/1/2016', 8),
('9/1/2016', 9),
('10/1/2016', 10),
('11/1/2016', 11),
('12/1/2016', 12),
('1/1/2017', 5),
('2/1/2017', 6),
('3/1/2017', 7),
('4/1/2017', 8),
('5/1/2017', 9),
('6/1/2017', 10),
('7/1/2017', 11),
('8/1/2017', 12),
('9/1/2017', 13),
('10/1/2017', 14),
('11/1/2017', 15),
('12/1/2017', 16)
select Event_Date, format(Event_Date, 'dd/MM') as DayMonth, year(Event_date) as Yr, Attendance from #t
Notice in the final select (the bit you actually need) I've added a year column Yr and a day/month column DayMonth. With your dataset as it was, even if you split by year the x axis would still represent the date so the you two lines would have been next to each other rather than one on top of the other which is what I expect you want....
The result of the dataset gives us something like...
Event_Date DayMonth Yr Attendance
2016-01-01 01/01 2016 1
2016-02-01 02/01 2016 2
.....
.....
2017-01-01 01/01 2017 5
.....
.....
And so on..
Now, add a new line chart and drop Attendance into Values; DayMonth into Category Groups and Yr into Series Groups.
Your chart design should look something like this...
That's it!
When we run the report we get this...
Thanks so much for the help. It pushed me in the right direction so that I could make things work for the situation.
I made some changes to the query so that I could align all the data on top of each other by a yearly event number.
Here is the query:
select
ROW_NUMBER() over (PARTITION BY year([dbo].[#temp_table_4].[event_start_date]) ORDER BY [dbo].[#temp_table_4].[event_start_date]) as yearly_event_number
,format ([dbo].[#temp_table_4].[event_start_date],'d') as event_start_date
,format([dbo].[#temp_table_4].[event_start_date],'MM/dd') as MonthDay
,year([dbo].[#temp_table_4].[event_start_date]) as Year
, Count (*) as [Total Attended]
from
[dbo].[#temp_table_4]
Group by [event_start_date]
order by
[dbo].[#temp_table_4].[event_start_date]
The main change was that I needed to number each event that happened each year beginning with 1 and ending with 'n' (the last event of the year). I needed to do that because the events don't happen on the same date each year (they actually happen each Wednesday which is not the same date each year).
To account for this, I added the following SQL clause:
ROW_NUMBER() over (PARTITION BY year([dbo].[#temp_table_4].[event_start_date]) ORDER BY [dbo].[#temp_table_4].[event_start_date]) as yearly_event_number
In the chart, I assigned Total_Attendance to Values, yearly_event_number to Category Groups and Year to Series Groups. I also added a tool tip that showed the event date so that you can hover over any point and show the event date.
I'm making a graph in SSRS which will highlight the sales for each week from a specific week, and from 52 week up to that date.
For this I have created the following data set in SSRS:
WITH SET LAST52WEEKS AS
{
STRTOMEMBER("[Dim Date].[Week].&[2017]&[1]&[1]&[4]").Lag(52):
STRTOMEMBER("[Dim Date].[Week].&[2017]&[1]&[1]&[4]")
}
Select {[Measures].[Quantity]} ON 0,
{Last52Weeks} ON 1
FROM (
Select {
[Dim Store2].[Store Key].&[1024]
} on columns
from [DSV_FactStoreSales 1]
)
which works as intended, and have an output for week 13 through 4 with each week having a weekly sales Quantity>400 (except for one week with Quantity (null).
However, when I add this data as the Y-axis in a graph in SSRS along with Weeks attribute as the X-axis, only four rows are returned. The rows returned are for the weeks
1,19,3,40
All other values are blank in the graph. Does anyone have any idea as to why this may occur?
Regards,
Cenderze
EDIT updated x-axis from using Interval value = 1
When I changed the Interval value under Horizontal Axis Properties I now get the following values for the x-axis:
1, 13, 14,[...],19, 2, 20, 21, 22, 23, [...], 29, 3, 30, 31, 32,[...],39, 4, 41, 42,[...], 53
where I have bolded the results which seem odd. Im guessing these values are the quarters? I am however using Weeks as my Grouping variable.
EDIT
Following Mike Honey I figured that:
WITH SET LAST52WEEKS AS
{STRTOMEMBER("[Dim Date].[Date].&[1]&[2017-01-29]").Parent.Lag(52)
:
STRTOMEMBER("[Dim Date].[Date].&[1]&[2017-01-29]").parent}
Select {[Measures].[Quantity]} ON 0,
{Last52Weeks} ON 1
FROM (
Select {
[Dim Store2].[Store Key].&[1024]
} on columns
from [DSV_FactStoreSales 1])
ought to work, but it simply returned that Quantity was (null). Why isn't this equivalent to the other Query I wrote, but based off of Date rather than week?
EDIT
I also noted that the graph I am creating has week 52 to the utmost right, whereas it is supposed to have week 4 at the utmost right.
EDIT
EDIT
Edited the Query to become:
WITH SET LAST52WEEKS AS
{STRTOMEMBER("[Dim Date].[Hierarchy].&[2017 W4]").Lag(52):STRTOMEMBER("[Dim Date].[Hierarchy].&[2017 W4]")}
Select {[Measures].[Quantity]} ON 0,
{(Last52Weeks,[Dim Store2].[Store Name].Allmembers)} ON 1
from [DSV_FactStoreSales 1]
where Hierarchy is an Attribute Hierarchy with the values 2010 W1,...., 2018 W52.
But this yields me an output:
2016 W40 Store1 300
2016 W40 Store2 400
...
2017 W39 Store1 400
where I would expect the output to be:
2016 W4 Store1 300
2016 W4 Store2 400
...
2017 W4 Store1 400
Any ideas? It is just an hierarchy with one attribute, Week Name (I've tried the Query with both using [Dim Date].[Hierarchy].[Week Name].&[2017 W4] and [Dim date].[Hierarchy].&[2017 W4], both with the same output.
EDIT (very close now!)
There are two issues I can see with your current chart. One is that your week numbers are being treated as text, which is why the ordering has sequences like 19, 2, 20. The other is that it isn't distinguishing where the week numbers for one year ends and another year starts.
I'm not familiar with mdx. I'm hoping you're able to make a simple dataset that is purely a list of sales with dates. For my solution, I used an Oracle query like:
SELECT date SALEDATE, ID FROM sales
WHERE date BETWEEN '28-MAR-2016' AND '28-JAN-2017'
With a new chart, use [Count(ID)] for the values. It then needs two category groups, first one for the year and then one for the week number. You can use expressions to get these from a date field. For the first category group, set Group on: and Label as
=DatePart(DateInterval.Year, Fields!SALEDATE.Value)
and for the second, set Group on: and Label as
=DatePart(DateInterval.WeekOfYear, Fields!SALEDATE.Value)
To then hide the columns with under 400 sales, right-click the second category group (the weeks one) and add a filter: [Count(ID)] (integer) > 400.
Even if your dataset is different from the raw data approach I'm using, hopefully this will steer you in the right direction.
Right click on the x-axis and choose "Horizontal Axis Properties". Under Axis Options change the Interval value from Auto to 1.
I am creating a report and would like to retrieve data based on a date field (string) in the format YYYYWW. I want to filter the data so I retrieve the current month, previous month, the month before that and older values - using 4 different datasets.
For example:
201547 = November 2015
How do I create a calculated member which converts a string into the month name and year? I would like to use this value to filter out the data from the cube. Is there any other way of doing this?
:]1
Try adding a calculated field and set it to this expression:
=MonthName(Month(DateAdd("ww",CInt(MID("201547",5,LEN("201547")))
,DateSerial(CInt(LEFT("201547",4)),1,1)))) & " " & LEFT("201547",4)
Then use that field to filter your report.
Replace the string for the field returning "201547"
=MonthName(Month(DateAdd("ww",
CInt(MID(Fields!YearWeek.Value,5,LEN(Fields!YearWeek.Value)))
,DateSerial(CInt(LEFT(Fields!YearWeek.Value,4)),1,1))))
& " " & LEFT(Fields!YearWeek.Value,4)
UPDATE: MDX script for querying a calulated member with the required format:
I've tested with the following MDX:
WITH MEMBER [Measures].[month&year] AS
'FORMAT(DateAdd("ww",STRTOVALUE(MID("201547",5,LEN("201547"))) ,CDATE(DateSerial(LEFT("201547",4),1,1))),"MMMM") + " " + LEFT("201547",4)'
SELECT { [month&year] } ON COLUMNS
FROM [Your Cube]
To use it in your query replace "201547" for [Dimension].[Attribute].MemberValue that corresponds to your cube structure:
WITH MEMBER [Measures].[month&year] as
'FORMAT(DateAdd("ww",STRTOVALUE(MID([Dimension].[Attribute].MemberValue,5,LEN([Dimension].[Attribute].MemberValue)))
,CDATE(DateSerial(LEFT([Dimension].[Attribute].MemberValue,4),1,1))),"MMMM") + " " + LEFT([Dimension].[Attribute].MemberValue,4)'
SELECT
{ [Dimension].[Attribute].[Attribute] }
{[month&year]} ON COLUMNS
FROM [Your Cube]
Once you have this field in your dataset you can easily filter the values using a parameter.
Let me know if this can help you.
Using a combination of the resources found out on the internet you can find the information you require.
First you need to find the first day of the first week of the year. This has already been determined by this answer as
DateAdd("d",
(-1) * (CInt(New DateTime(Year(Now), 1, 1).DayOfWeek) +
IIf(CInt(New DateTime(Year(Now), 1, 1).DayOfWeek) < DayOfWeek.Monday,
7,
0)
) + 1,
New DateTime(Year(Now), 1, 1))
This needs to be adapted for any year - not just the current one by finding the year from the string as follows
CInt(Left(Parameters!myDate.Value,4))
Now, as noted in this resource you can use a DateAdd to add the number of weeks of the year you have entered to the first date of the year
=(DateAdd(DateInterval.WeekOfYear,
CInt(Right(Parameters!myDate.Value,2))-1,
<<FIRST_DAY_OF_YEAR>>)
You then want to get the month name of the month of this date, using Month and MonthName. Smashing it all together would result in the following
=MonthName(Month(DateAdd(DateInterval.WeekOfYear,
CInt(Right(Parameters!myDate.Value,2))-1,
DateAdd("d",
(-1) * (CInt(New DateTime(CInt(Left(Parameters!myDate.Value,4)), 1, 1).DayOfWeek) +
IIf(CInt(New DateTime(CInt(Left(Parameters!myDate.Value,4)), 1, 1).DayOfWeek) < DayOfWeek.Monday,
7,
0)
) + 1,
New DateTime(CInt(Left(Parameters!myDate.Value,4)), 1, 1))
)))
This will get a Textual value of the month for the interval
Create a new placeholder in the same textbox and then repeat the above for finding the year
=Year(DateAdd(DateInterval.WeekOfYear, ...
(Remember to remove the last brace otherwise you’ll get a End of Statement expected error.)
This shoud give what you require, so
201501 = December 2014
201547 = November 2015
201553 = December 2015
201622 = May 2016
Let me know if this helps, or if you have further questions
Part 1: Establishing which day falls into which week
ISO-8601 declares the international standards for converting dates into week numbers, and vice-versa.
ISO standard weeks start on a Monday. A year can have either 52 or 53 weeks.
There are 4 ways of establishing when Week 1 starts:
- It is the first week with a majority (4 or more) of its days in January.
- Its first day is the Monday nearest to 1 January.
- It has 4 January in it. Hence the earliest possible dates are 29 December through 4 January, the latest 4 through 10 January.
- It has the year's first working day in it - i.e. excluding Saturdays, Sundays and the 1st of January.
Part 2: Excel calculations
This answer assumes that the dates are being stored as 6-character strings.
First determine the year and what day of the week it starts on.
1) Strip the first four characters from the string.`
=left(<cell containing the year+week string>, 4)
2) Prepend "1/1/" to it.
="1/1/"&left(<cell containing the year+week string>, 4)
3) Convert this string to an Excel date
=datevalue(<the last result>)
4) Determine the Weekday of the 1st day of that year.
=weekday(<the last result>)
5) Calculate the Excel date of the first Monday.
=if((<the last result>-4)<0,<the result of step 3>+8-<the last result>, <the result of step 3>+1-<the last result>)
6) Work out how many weeks on from that we are:
=right(<original 6 char year/week string>,2)
7) Convert 6) to a number
=value(<last result>)
8) Add that to the Monday of Week 1
=<result of step 5>+<result of step 7>*7
9) Convert this to a month number
=month(<last result>)
10) Convert this to a month name
=choose(<last result>,"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec")
11) Add the year back on
=<lastresult>&" "&<result of 1>
This gives the month number which contains the Monday of the current numbered week.
If cell A1 contains '201547
then cell B1 should contain:
=CHOOSE(MONTH(IF((WEEKDAY(DATEVALUE("1/1/"&LEFT(A1,4)))-4)<0,DATEVALUE("1/1/"&LEFT(A1,4))+1-WEEKDAY(DATEVALUE("1/1/"&LEFT(A1,4))),DATEVALUE("1/1/"&LEFT(A1,4))+8-WEEKDAY(DATEVALUE("1/1/"&LEFT(A1,4))))+7*(VALUE(RIGHT(A1,2)))),"January","February","March","April","May","June","July","August","September","October","November","December")&" "&LEFT(A1,4)
If A1 contains 201547 then B1 returns "November 2015".
Further considerations:
You may want to make it more sophisicated, so that a month ending in a Monday does not have the week commencing with its final Monday counted as part of the month. More generally, that week only counts as part of a month is 3 or more of the days are in the month. Or 3 or more of its working days are part of the month.
As it is, I would sort with the calculated month and year as primary key and the YYYYMM code as secondary key.
I've got a chart that overlays the past 2 years (taken from the current date) worth of data onto a 1 year range, so the monthly values can be compared between years. The x-axis values are week numbers.
Currently, I've got the x-axis like this:
-------------------- etc
1 2 3 4 5
What I want is to start the x-axis with the week for the earliest date in my data set, so my x-axis looks like this:
--------------------------...-------
49 50 51 52 1 2 3 ... 47 48
How do I get the chart control to get my x-axis to appear like this?
You need to have another column that contains the year, sort by this first, then the week number, then only display the week number in the axis.
So assuming your data is something like:
You would apply two sorts to the category group, Year then Week, but only display Week in the axis label.
I have left all the Category Axis Properties as default:
This gives the expected result:
I have a SSRS 2008 report that generated columns of the months along with other data based on year halves. I have the tablix column group and sort set for [Mon] and the first half of the year generated just fine but when I run the report for the second half it does not display in order :
MonthNumber 10 11 12 7 8 9
MonthName October Movember December July August September
The SQL code that is used generated the following rows which appear in order of month number.
Mon
7
8
9
10
11
12
I would say that Mon is being treated as a string value, for whatever reason, i.e. from the query or in the dataset definition, as you can see that in your example the columns are being sorted as strings, i.e. 10 will be before 7 when sorted as text and not numeric values.
You have two options:
First is to sort by an expression like: =CInt(Fields!Mon.Value), i.e. explicitly sorting as an integer, which solve the issue if Mon is being treated as text.
The other option is to make sure that Mon is being treated as an integer at the dataset level - either way should be fine.