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.
Related
I am building a report with 2 matrix tables with different (but very similar) data sets. I need to calculate the average daily transaction amount where the user inputs the month and year they want to see. I was able to use the following expression on the first table with no issue.
=sum(fields!tot_rev.Value)/fields!Day.Value
Where "Day" is the day of the month. I used "Day(trn_dt) as Day" in my query to extract the day from the datetime string.
I tried using the same expression in my second table but it only returns the sum total amount. If I use
=sum(fields!amt.Value)/countdistinct(fields!Day.Value)
it returns a value that seems to be random (I don't know how it came to that value with any calculation)
The only way I have been able to successfully get the average was by inputting the number of days in the expression.
=sum(fields!amt.Value)/22
But I need this to work with the parameters and the number of days will not be constant.
Here is a sample of my data from dataset1:
SELECT MONTH(inv_dt) AS Month, DAY(inv_dt) AS Day, YEAR(inv_dt) AS Year, bill_by, inv_no, tot_rev
FROM inv_info
WHERE (status_cd IN ('FF', 'FP')) AND (MONTH(inv_dt) = #Month) AND (YEAR(inv_dt) = #Year)
Month, Day, Year, bill_by, inv_no, tot_rev
10, 23, 2020, ERSA, 40444, 4881
10, 23, 2020, ERSA, 40443, 2043
10, 22, 2020, DYCO, 40435, 2504
10, 22, 2020, ERSA, 40431, 20524
Here is sample from dataset2 (table with the problem):
SELECT YEAR(trn_info.trn_dt) AS YEAR, MONTH(trn_info.trn_dt) AS MONTH, DAY(trn_info.trn_dt) AS Day, trn_info.reg_no, trn_dtail.amt, trn_info.acc_by
FROM trn_info LEFT OUTER JOIN
trn_dtail ON trn_info.trn_no = trn_dtail.trn_no
WHERE (trn_info.status IN ('FP', 'FF')) AND (trn_info.tpe_cd IN ('AI', 'BI')) AND (trn_dtail.rte_cd = 'TT') AND (MONTH(trn_info.trn_dt) = #Month) AND (YEAR(trn_info.trn_dt) = #Year)
Year, Month, Day, reg_no, amt, acc_by
2020, 10, 1, 40113, 377.96, JLMA
2020, 10, 1, 40115, 6637.07, NASO
2020, 10, 2, 40104, 790, MCGO
2020, 10, 2, 40106, 1406.25, MCGO
2020, 10, 3, 40100, 239.77, JEDX
In the attached picture the upper left corner expression is: =MonthName(Fields!MONTH.Value,false)
The day of month is listed along the left with the total count (count of transactions) and sum for each processor(acc_by/bill_by) in the data field.
I used =iif(isnothing(Sum(Fields!amt.Value)), 0, sum(fields!amt.Value)) as the expression for the amt field.
The column total is the total count and sum for that day from all processors.
The row total at is the average daily count and average daily amt by processor and where the total column and total row intersect it is the average daily count for the month and I would like to show the average daily transaction amt for the month as well but this is what isn't working properly.
See attached image:
image of table 2
Does anyone know what else I can try?
Don't break a date down into its component parts until you are presenting it, and even then use formatting to display the date part without converting the date to ints or strings. So many calculation bugs are introduced this way.
Leave inv_dt and trn_dt as Datetime values in your query and bring them into SSRS that way. Within SSRS, use the date formatting values to show just the year or month.
To calculate your daily average, create a grouping in the SSRS report on the date. Choose an easily understood group name, like InvoiceDate or something. Then use Avg(fields!amt.value,"InvoiceDate"). This will tell SSRS to average the amount within the grouping (each day). If desired, you can than average the average by Avg(Avg(fields!amt.value,"InvoiceDate")).
Please take the time to learn how to manipulate dates in SQL and SSRS. Your query results will be more accurate and your peers will thank you when maintaining your code.
As a sample of what I'm talking about, see if you can spot the logic bug in some DB2 code I'm updating this week (Hint problem happens in January:
AND Month(CUST.acct_svc_strt_d) >= (Month(CURRENT DATE) - 1)
AND Year(CUST.acct_svc_strt_d) = Year(CURRENT DATE)
We have a SSRS Matrix report with the following areas
RowGroup:MonthYear
ColumnGroups:Campaign,Year,Processed
Detail:Sum(Processed)
We have added a single column outside of the ColumnGroup for and expression that will show the increase/decrease of current year processed records over previous year processed records
The data is shaped like this:
lYear, MonthYear, Campaign, Processed
2014, JUL-10, XYZ, 120
2015, JUL-10, XYZ , 60
So the formula is basically CurrentYearProcessed/PreviousYearProcessed which in this example would yield 50%
So how can we specify this when writing the expression?
Just use IIF to filter for the year:
=SUM(IIF(FIELDS!lYear.VALUE = YEAR(GETDATE()), FIELDS!Processed.VALUE, 0) / SUM(IIF(FIELDS!lYear.VALUE = YEAR(GETDATE()) - 1, FIELDS!Processed.VALUE, 0)
This checks your lYear field to see if it's the same as the current year [ YEAR(GETDATE()) ] and sums the Processed field. Then it divides by the previous year's SUM using similar logic.
I have a script with result set something like this:
-- #Test (temptable)
Branch_Name C_Date Percentage
Branch 1 20140107 90
Branch 1 20140108 82
Branch 2 20140107 85
Branch 2 20140108 86
I would like to pivot this data, however the C_Date is populated to get 7 days back:
WHERE (1 = 1) AND
(tTable.C_Date > CONVERT(VARCHAR(10),GETDATE() -7, 112)) AND
(tEnter.C_Date < CONVERT(VARCHAR(10),GETDATE() -1, 112)).
I've tried
Select * from #Test
pivot (avg (Percentage) for C_date in ([20140107],[20140108])) as PivotTable
and it gives me the data I want (see below),
Branch_Name 20140107 20140108
Branch 1 90 82
Branch 2 85 86
but how do I get the pivot to look at dates populated by the GETDATE? I've tried putting the GETDATE command in each [] but that obviously didn't work.
** Note, my example shows 2 days, but my query is for 7 days back, not including the day it's being run.
Any help appreciated - thank you!
Instead of trying to work with the dates, try working with "the number of days between C_Date and today".
So early on (in a subquery or CTE) you do DATEDIFF(day,C_Date,GETDATE()) as NumDays.
You can then filter your where as WHERE NumDays between 1 and 7 and your pivot as:
pivot (avg (Percentage) for NumDays in ([1],[2],[3],[4],[5],[6],[7])) as PivotTable
Now, that handles most of what you need. The one thing we can't do (in plain SQL) is to convert those column names back into dates - because any particular SQL query has to produce a result set with a fixed "shape" - the number, names and types of the columns are fixed.
But hopefully that's enough to do in SQL, and if you do need to convert back into date headings, that can be done with whatever is consuming this result set.
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.
I have a dataset that is going to get passed to an SSRS report that looks like this:
CODE TEXT COUNT MONTH
100 ABC 20 January
100 ABC 10 February
200 DEF 15 January
200 DEF 15 February
300 GHI 0 x
400 JKL 10 January
This 'x' indicates there is no data for that code/text for the current year, however, I still need it to display. In SSRS I want to have a column to display for the current month (February) and a column to display for year to date:
CODE TEXT MONTH_TO_DATE YEAR_TO_DATE
100 ABC 10 30 [20 + 10]
200 DEF 15 30 [15 + 15]
300 GHI 0 0 [0]
400 JKL 0 10 [0 + 10]
Is this possible in SSRS 2008?
This is going to have to be done in SQL so it would be easier to adjust the SQL if you posted what you have already, rather than the data resulting from that SQL.
Anyway, we have to find a way to know it is the current month and display it, which we can do with the SQL CASE statement. Maybe you have a date field you can query which might be cleaner than below, but I'll just run with the data as you have provided (that is, we just have a month name which we compare to the current month using the DATENAME and GETDATE SQL functions - obviously this doesn't work if you have multiple years of data as every February will be aggregated into the current month, but you get the idea for what to do):
SELECT [CODE], [TEXT],
SUM(CASE WHEN [MONTH] = DateName(month, GetDate()) THEN [COUNT] END) AS CurrentMonth,
SUM([COUNT]) AS YearToDate
FROM MyTable
GROUP BY [CODE], [TEXT]
ORDER BY [CODE], [TEXT]
Now, in your comment on Vlad's answer you say you can't do a SUM(COUNT(fieldname)) which you can actually do if you use nested queries, like so:
SELECT [CODE], [TEXT], SUM([COUNT]) AS Total
FROM ( -- This is a nested query
SELECT [CODE], [TEXT], COUNT(somefield) AS [COUNT]
FROM MyTable
)
GROUP BY [CODE], [TEXT]
ORDER BY [CODE], [TEXT]
If you want to display x for the zero values then use the following Format for the YearToDate cell:
#,##0;-#,##0;x
This can be done in either SQL or SSRS - doing it in SQL (as described by Chris Latta) should be simpler and more efficient, but if that option is not available, here is how to do it in SSRS:
Add a 4-column table to the report, with the appropriate dataset.
Add a group (including group footer) on your CODE and TEXT columns to the table.
Add your CODE and TEXT values to the group footer.
Delete (or hide) the Details section row on your report.
Enter the following expression into the appropriate cell in the group footer row for the year-to-date column:
=Sum(Fields!COUNT.Value)
Enter the following expression into the appropriate cell in the group footer row for the month-to-date column:
=Sum(iif(MonthName(DatePart("m",Now()))=Fields!MONTH.Value,Fields!COUNT.Value,0))
I think you should return this from the sql select/stored procedure. You should use a LEFT JOIN i think for those 0 results