SSRS - grouping with ceiling - reporting-services

I'm creating a SSRS-report where I need to group my values and do another grouping based on the grouped values. Then I also want to limit the records on each row.
Now my table look like this (but with maybe 50 values):
A
A
A
B
C
C
D
E
E
F
(ignore the bullets, it was the only way to get the values vertical)
I want my table to fit in one page and become horizontal and be grouped.
The result I'm after look like this:
A, B, C,
D, E, F
I writing this in MDX because I need to have data direct from the cube.
I would have a great solution if i didn't have to group the values together.
It's was to use the ceiling-function (ceiling(rownumber(nothing) mod 6)) in ColumnGroup and (=ceiling(rownumber(nothing) / 6)) in RowGroup.
Has someone a solution, maybe a nested expression to both group the values and then do the ceiling trick?

Perhaps you can add a calculated field to the dataset, GroupID, with a value based on the position in the alphabet and your paging requirement.
For example :
Letter GroupID
A-F 1
G-L 2
M-Q 3
Next you can group similar to below.
Column Group 1 Expression = GroupID
Column Group 2 Expression = Letter
You may wish to place a page break after group for Group1 to force repeats on a new page.

Related

Calculate Min and Max for aggregation in SSRS report

My SSRS report have a dataset that will return the following result. The result set for some reason may not be changed. Note that Category - SubCategory pair might not be distinct.
Category Sub-Category Value
-----------------------------
A A1 100
A A2 120
A A2 60
B B1 80
B B2 90
B B2 70
I want to show the max value and main value for each of the SUM(category, subCategory) in report matrix, as exactly the format as follows (except the comment in bracket):
Max | 180 (two A-A2 rows)
Min | 80 (B-B1)
How can I define the matrix and write the expression? If make a group on these two columns, The matrix will show four rows regardless of what expression I set.
I tried to run your use case on my local SSRS.
On Left hand side I have original Data and on Right hand side I have the desired result you expect.
What you need is grouping as below
Expression for sum as below
Put a tablix into your report. Then at Row Groups (bottom) click on the (Details) and chose Add Group > Parent Group. Click the Add group header and chose your Sub-Category. Do the same with your Category. Your Row Grouping hierarchy should be now Category > Sub-Category > Details.
Now you see the brackets on the left in your tablix, they indicate the level. If you use now the following expression with their group name on the specific level, you will get what you want.
'At the Category group level header
=Sum(Fields!Value, "CategoryGroupName")
'At the Sub-Category group level header
=Sum(Fields!Value, "SubCategoryGroupName")
I got the way to make it. The solution is as follows:
Make a row parent group called row. Let the group group by a constant.
Make a child group category under the row group which is grouped by Category.
In matrix cell which is inside the group, Add this expression: =Min(Sum(Fields!Value.value), "Category"), "row"). that's the reason why I make a constant group, because I want to make the nested aggregate function legal.
This expression will return all values identical within the Category group. Now add another row outside of these row groups. Pick a cell and enter =ReportItems!ThatTextBox.Value.
Hide the row which consists your groups.
Do the same for MAX value (Start from adding an adjacent group, grouping by constant)

How can I make empty groups of a bar chart visible in SSRS?

I have a bar chart that displays # of Work Orders on the X axis and groups them into 3 categories on the Y axis (Overdue, 0 to 7 days, 8 to 28 days). The report is setup for the user to select a parameter (in this case an NYC boro) in order to run the report. In some cases, the borough selected does not return values for all 3 of the groups on the Y axis. How do I force SSRS to display all of the categories on the Y axis even when those groups are empty. In the example image included, the "0 to 7 Days" category is not showing up.
You need to create a table with a list of your categories in and then left join your current query to that. Without seeing your current query I can;t give the best answer as you may already have all the categories in a table that you could already use but this will still work...
DECLARE #cat TABLE(CategoryName varchar(20))
INSERT INTO #cat VALUES
('Overdue'),
('8 to 28 days'),
('0 to 7 days')
SELECT
c.CategoryName, q.*
FROM #cat c
LEFT JOIN (SELECT * FROM YourOriginalQuery) q
ON c.CategoryName = q.myOriginalCategoryName
As you are now left joining from a list of categories, each category name will be present in your dataset (unless of course your WHERE clause filters it out).
If you edit your question showing your current query, there may be a much better way to achieve the same result.

SQL query for operation between rows under some condition

Its little complicated query as it contains some conditions.
I have tables like this:
table DC - which contains one row for one northing-easting pair
Columns - Id Northing Easting
PossibleValues - Guid Std value Std value
table DCR - which contains multiple rows for each row in DC. Each row here corresponds to data on each pass on that exact location.
Columns - Id VibStatus DrivingDir CompactionValue UtcDate
PossibleValues - Guid 0/1 Forward/Reverse/Neutral +ve integers Timestamp
table DCMappings - which contains mapping between both tables.
DCId DCRId
The output I need should contain fields like this:
ResultTable
DCId DCRId Northing Easting VibStatus DrivingDir CompValue Position CompProgress
Here, Position is its position in chronological order when sorted by UtcDate grouped by DC.Id(See query at end to understand more).
And CompProgress has some conditions which is making it complicated.
CompProgress is percentage increase/decrease in CompValue compared to its previous row which was in same driving direction when arranged in ASC order of UtcDate(chronological) where the rows to be considered here should only be the ones with VibStatus set to ON(1) grouped by DCId's.
Each row in DC has multiple rows in DCR. So if row 1 in DC has 10 rows in DCR, the CompProgress should consider these 10 rows alone for calculation and then for row 2 in DC, etc...
I have written following query to extract needed fields except calculation of CompProgress. Please help me in this.
SELECT DC.Id, DCR.Id, Northing, Easting, VibStatus, DrivingDir, CompValue, ROW_NUMBER() OVER (PARTITION By dcm."DCId" ORDER BY dcr."UtcDate") as passNo
FROM "DCR" dcr LEFT JOIN "DCMappings" dcm ON "Id" = dcm."DCRId"
LEFT JOIN "DC" dc ON dc."Id" = dcm."DCId"
Need evaluation of CompProgress in this query.
Sorry for lot of text. But it was necessary to make others understand what is needed.

SSRS List formatting

Need to make a list in SSRS that has a numbered range from 0-30 in the rows and allows for null values to be entered in as a dash. i.e if I have 8 players who scored 10 points the list would show an 8 in the row value next to the row value 10 but for the other 29 numbers it would show a dash(-)?
You may have to make a couple of adjustments, but this should get you most of the way there. There wasn't a lot of information to go by to determine exactly what you want.
Adjust your dataset query in SSRS to the following, replacing the subquery Z with your current query that provides the points and player count. I inserted dummy data in there for now so I would have data for this example (8 = 1, 13 = 1, 17 = 2).
With X as
(
select top (30) n = ROW_NUMBER() OVER (ORDER BY m1.number)
from master.dbo.spt_values as m1
CROSS JOIN master.dbo.spt_values as m2
)
,Y as
(
Select Points, PlayerCount, ROW_NUMBER() OVER (Order by PlayerCount) RowNum
from (
--replace this with your query to return the data
--with your 2 columns for points and player count
Select 8 as Points, 1 as PlayerCount
UNION
Select 17 as Points, 2 as PlayerCount
UNION
Select 13 as Points, 1 as PlayerCount) Z
)
Select x.n as Points, /*isnull(Y.Points,0),*/ Isnull(Y.PlayerCount,0) PlayerCount
from X
left join Y on X.n = Y.Points;
The CTE labeled X is what creates the 30 spots. If you want it to be 31 spots (0 - 30 inclusive), change the query in X to be
select top (31) n = ROW_NUMBER() OVER (ORDER BY m1.number)-1
from master.dbo.spt_values as m1
CROSS JOIN master.dbo.spt_values as m2
You end up with a data set with 2 columns: Points and PlayerCount.
Now create your list in SSRS.
Insert a list. In that list, insert 2 columns to the right. Then delete the left most (original) column.
Set the expression for the left textbox in the list to the points field.
Set the expression for the right textbox in the list to the PlayerCount field.
Add a row outside the group above. Type in column headers for each column. I used Points and Player Count.
In the Group Properties for the Details row group, go to Sorting and set the Sort By column to points. The order should be A to Z.
Adjust the height of the rows to whatever looks best to you. I used .25 for the header and detail rows.
In the Tablix properties, check the box next to Keep together on one page if possible.
On the text box containing the Player Count field (bottom right), go to text box properties, Number category. Set it to 0 decimal places. Check the box next to Show zero as:. Make sure - is selected.
That gives you a list that looks like this:
If for some reason you want to see only the numbers that have > 0 players with that amount of points at the top and then the rest, you can do this with a calculated column.
Right click on your data set and add a calculated field. Set the Name to PointsCountSort. The the expression to =iif(Fields!PlayerCount.Value = 0, 2, 1)
. Click OK.
In the Sort Order of the Details group. Change the sort order to go by PointsCountSort A to Z then Points A to Z.
That makes the list sorted like this:

Populating with '0' when Data in SSRS Does not exist

I'm trying to create a report in SSRS where I have a matrix, which has gender as the column headings and specifically defined agegroups as the rows. The report is sorted by date (ie, the records being displayed are filtered by the modifedAt value). My problem is that i wish for all of the age group categories to be displayed, even if the dataset does not return any data for that row.
So, for example, if i set the date to be a date where there are no db rows where there are Age5-16 children in - I still want to display the category name, but just have the cells related to that row to display '0'. Instead, the report just drops the whole row because, obviously the query returns no data.
Is the solution to have a separate dataset that brings back the entire list of categories and then somehow fit them together? I'm stuck here so any help is appreciated!
I can think of a few ways to do this:
DataSet level
Instead of just returning the relevant data in the underlying data in the DataSet, include all the categories you want to display in all cases.
e.g. For a database query it might be the difference between an inner and left join, i.e. going from something like:
select *
from AgeGroup
inner join MyData on ...
to:
select *
from AgeGroup
left join MyData on ...
So the report always has all the age groups to display. Where there are NULL values, just display 0.
I think this is the best option if you have control over the DataSet - you won't have to update your report at all, with luck the actual DataSet changes should be minimal, there is still only one DataSet call, and it's by far the simplest to maintain.
Hard code groups into the report
Here you include a table header row for each group you want to display, so these are always displayed in all cases.
Here you have some sort of conditional expression to display the values, e.g. For each group row it will be tailored to that group:
=Sum(IIf(Fields!AgeGroup.Value = "5-16", Fields!Amount.Value, Nothing)
This is not too flexible and will need updates as you change groups, and doesn't have as many options for layout. There is still only one DataSet call, so that is a plus.
Subreports
You can have a parent DataSet that displays one row for each age group, then embed a subreport in each row that displays the data you want for that row.
This allows you flexibility in layout but it will add complexity to the report(s) and will mean that you make a lot of DataSet calls that could be avoided with other options.
I know this is old, but I wanted to elaborate on Ian's section 1 above using joins at the dataset level. (His answer was super helpful to me for a report I'm working on.)
per op:
Is the solution to have a separate dataset that brings back the entire list of categories and then somehow fit them together?
That is how I've handled it successfully, but you can do so without actually creating a separate dataset by using common table expressions (or temp tables, of course).
For these example tables:
AGE_Table
ID Group Group_Desc Toys
1 A 00-10 Teddy Bear
2 B 11-20 Video Game
3 C 21-30 Sports Car
4 D 31-40 Mansion
5 E 41-50 Jewelry
People_Table (filtered for whatever date)
ID Name Age Gender Age_Group
1 Ariel 07 F A
2 Brandon 23 M C
3 Chelsea 27 F C
4 Derek 06 M A
You want to see 2 results for the 00-10 row, 2 for the 21-30 row, and then still see rows for the other age groups even if there aren't any results.
We want to create a dataset with all the different age groupings and then join on it. Behold a solution using common table expressions:
with CTE_Age AS
(SELECT Distinct Age_Group from AGE_Table)
SELECT ID, Name, Age, Gender, CTE_Age.Age_Group FROM People_Table
RIGHT JOIN CTE_Age ON
People_Table.Age_Group = CTE_Age.Age_Group
This will return:
ID Name Age Gender Age_Group
1 Ariel 7 F A
4 Derek 6 M A
NULL NULL NULL NULL B
2 Brandon 23 M C
3 Chelsea 27 F C
NULL NULL NULL NULL D
NULL NULL NULL NULL E
Once you have that in your dataset, you can change NULL values to 0 on the report builder side -- I think in 2008R2 the default is just blank.