SSRS 2008 R2 - How to aggregate group data based on inner group filters? - sql

I have made a simplified example to illustrate the question i'm trying to ask here. In my example i have sales orders and each sales order has multiple lines, i group by Sales Order Number, then by Sales Order Line (row groups)
I have found Group Filters very useful/flexible in filtering report data in specific areas of a table, so in my example i filter the SOLine group to exclude the SO line if it equals 3.
Then, i want to have a group aggregate for the entire SO, to tell me a count of the SO lines within it. Unfortunately when doing COUNT() expression from a textbox within the Sales Order Number group scope it counts all the lines, including the SO Line 3, whereas i want it to take into consideration the line filtered out from its child group.
Below is a screenshot of my tablix and grouping:
On the SOLine group i have the following filter:
And below is the output i get when previewing the report:
I want that count to evaluate to 4, but i ideally want to keep using groups as i've found they are much more efficient than using SUM(IIF) which completely slowed down my actual report which has thousands of rows.
If this is not possible, please give all best alternatives i could use.
Many thanks.
Jacob

Related

PowerPivot Ranking Groups using DAX's Rankx - Ranking Using Sum of a Field

Am trying to rank groups by summing a field (not a calculated column) for each group so I get a static answer for each row in my table.
For example, I may have a table with state, agent, and sales. Sales is a field, not a measure. There can be many agents within a state, so there are many rows for each individual state. I am trying to rank the states by total sales within each state.
I have tried many things, but the ones that make the most sense to me are:
rankx(CALCULATETABLE(Table,allexcept(Table,Table[AGENT]),sum([Sales]),,DESC)
and
=rankx(SUMMARIZE(State,Table[State],"Sales",sum(Table[Sales])),[Sales])
The first one is creating a table where it sums sales without grouping by Agent. and then tries to rank based on that. I get #ERROR on this one.
The second one creates a table using SUMMARIZE with only sum of Sales grouped by state, then tries to take that table and rank the states based on Sales. For this one I get a rank of 1 for every row.
I think, but am not sure, that my problem is coming from the sales being a static field and not a calculated measure. I can't figure out where to go from here. Any help?
Assuming your data looks something like this...
...have you tried this:
Ranking Measure = RANKX(ALL('Table'[STATE]),CALCULATE(SUM('Table'[Sales])))
The ALL('Table'[STATE]) says to rank all states. The CALCULATE(SUM('Table'[Sales])) says to rank by the sum of their sales. The CALCULATE wrapper is important; a plain SUM('Table'[Sales]) will be filtered to the current row context, resulting in every state being ranked #1. (Alternatively, you can spin off SUM('Table'[Sales]) into a separate Sales measure - which I'd recommend.)
Note: the ranks will change based on slicers/filters (e.g. a filter by agent will re-rank the states by that agent). If you're looking for a static rank of states by their total sales (i.e. not affected by filters on agent and always looking at the entire table), then try this:
Static Ranking Measure = CALCULATE([Ranking Measure], ALLEXCEPT('Table', 'Table'[State]))
This takes the same ranking measure, but removes all filters except the state filter (which you need to leave, as that's the column you're ranking by).
I did figure out a solution that's pretty simple, but it's messier than I'd like. If it's the only thing that works though, that's okay.
I created a new table with each distinct state along with a sum of sales then just do a basic RANKX on that table.

Ignore suppressed records in crosstab

My report shows only the latest diagnosis per patient based on their date_of_diagnosis - all other records are suppressed:
I summarize by diagnosis and age group in a crosstab. Crosstabs evaluate before printing, so any attempts to suppress, share variables, or summarize happen after the crosstab populates. This means Total in Each Age Group is correct, because each patient only has one age - but if a patient has more than one diagnosis, even if they're suppressed, they get counted multiple times:
I absolutely must use a crosstab for this due to the large number of diagnoses and age groups involved. How can I get the crosstab to ignore suppressed records? Or if I need to use a custom SQL Command table, how can I rewrite the existing SQL to ignore obsolete records?
Crystal's auto-generated SQL (through ODBC):
SELECT "Codes"."diagnosis_code",
"Codes"."diagnosis_value",
"Codes"."PATID",
"Codes"."FACILITY",
"Codes"."EPISODE_NUMBER",
"Record"."date_of_diagnosis"
FROM "SYSTEM"."Codes" "Codes",
"SYSTEM"."Entry" "Entry",
"SYSTEM"."Record" "Record"
WHERE "Codes"."DiagnosisEntry"="Entry"."ID" AND
"Codes"."EPISODE_NUMBER"="Entry"."EPISODE_NUMBER" AND
"Codes"."FACILITY"="Entry"."FACILITY" AND
"Codes"."PATID"="Entry"."PATID" AND
"Entry"."DiagnosisRecord"="Record"."ID" AND
"Entry"."EPISODE_NUMBER"="Record"."EPISODE_NUMBER" AND
"Entry"."FACILITY"="Record"."FACILITY" AND
"Entry"."PATID"="Record"."PATID"
You need only the latest diagnosis among a set of diagnoses. So I would suggest:
SELECT "Codes"."PATID",
"Codes"."diagnosis_code",
"Codes"."diagnosis_value",
"Codes"."FACILITY",
"Codes"."EPISODE_NUMBER",
"Record"."date_of_diagnosis"
FROM "SYSTEM"."Codes" "Codes",
"SYSTEM"."Entry" "Entry",
"SYSTEM"."Record" "Record"
WHERE "Codes"."DiagnosisEntry"="Entry"."ID" AND
"Codes"."EPISODE_NUMBER"="Entry"."EPISODE_NUMBER" AND
"Codes"."FACILITY"="Entry"."FACILITY" AND
"Codes"."PATID"="Entry"."PATID" AND
"Entry"."DiagnosisRecord"="Record"."ID" AND
"Entry"."EPISODE_NUMBER"="Record"."EPISODE_NUMBER" AND
"Entry"."FACILITY"="Record"."FACILITY" AND
"Entry"."PATID"="Record"."PATID"
AND "Entry"."date_of_diagnosis" = (SELECT MAX("date_of_diagnosis") FROM
"DiagonsisRecord" "A" WHERE "A"."DiagnosisRecord"="Entry"."DiagnosisRecord" )
This should get the maximum Date_of_Diagnosis for each patient and pass the filter parameter to get the last diagnosis of that patient.
Building off of Muffaddal Shakir's answer, I was able to write this query to perform the correct filter:
SELECT "Codes"."PATID",
"Codes"."diagnosis_code",
"Codes"."diagnosis_value",
"Codes"."FACILITY",
"Codes"."EPISODE_NUMBER",
"Record"."date_of_diagnosis"
FROM "SYSTEM"."codes" "Codes",
"SYSTEM"."entry" "Entry",
"SYSTEM"."record" "Record"
WHERE "Codes"."DiagnosisEntry"="Entry"."ID" AND
"Codes"."EPISODE_NUMBER"="Entry"."EPISODE_NUMBER" AND
"Codes"."FACILITY"="Entry"."FACILITY" AND
"Codes"."PATID"="Entry"."PATID" AND
"Entry"."DiagnosisRecord"="Record"."ID" AND
"Entry"."EPISODE_NUMBER"="Record"."EPISODE_NUMBER" AND
"Entry"."FACILITY"="Record"."FACILITY" AND
"Entry"."PATID"="Record"."PATID"
AND "Record"."date_of_diagnosis" = (
SELECT MAX("Record2"."date_of_diagnosis")
FROM "SYSTEM"."entry" "Entry2",
"SYSTEM"."record" "Record2"
WHERE "Entry2"."DiagnosisRecord"="Record2"."ID" AND
"Entry2"."EPISODE_NUMBER"="Record2"."EPISODE_NUMBER" AND
"Entry2"."FACILITY"="Record2"."FACILITY" AND
"Entry2"."PATID"="Record2"."PATID" AND
"Record"."PATID"="Record2"."PATID"
)
The key differences being:
The subquery uses unique aliases from the main query.
The last line "Record"."PATID"="Record2"."PATID" - Without this, the query only pulls back one diagnosis (the latest one in the whole system.) But now it checks for the latest diagnosis per person.

How to display n number of rows between two groups in SSRS 2010

Using SSRS 2010
I have Two groups YearMonth and Insured. I need to display only 50 records per page based on a group "Insured". So I have created parent group "GroupPageBreakOnly" and used this expression =CEILING(RowNumber(Nothing)/50).
I ensured that the Page Break at end is checked so that individual groups appear in individual page.
As a result the first page displays 31 rows, the second one 50 rows, and the third one 9 rows.
I tried to specify data region "Insured"
=CEILING(RowNumber("Insured")/50),
but it gives me an error:
...the value of the scope parameter of RowNumber must equal the name of the group directly containing the current group.
What am I missing here?
Unless you need this report to do other things, I would apply the grouping and aggregation in the Dataset itself which is generally a lot more efficient anyway.
Have you tried using ROW_NUMBER() OVER (PARTITION BY YearMonth, Insured ORDER BY YearMonth, Insured) to give the number of rows, perhaps even throwing in a % 50 at the end to see which group of 50 it fell into?
This can then be grouped on in your report.

Create one query with sum and count with each value pulled from a different table

I am trying to create a query that pulls two different aggregated values from three different tables during a specific date range. I am working in Access 2003.
I have:
tblPO which has the high level purchase order description (company name, shop order #, date of order, etc)
tblPODescription which has the dollar values of the individual line items from customers the purchase order
tblCostSheets which as a breakdown of the individual pieces that we need to manufacture to satisfy the customers purchase order.
I am looking to create a query that will allow me, based on the Shop Order #, to get both the sum of the dollar values from tblPODescriptions and the count of the different type of pieces we need to make from tblCostSheets.
A quick caveat: the purchase order may have 5 line items for a sum of say $1560 but it might take us making 8 or 9 different parts to satisfy those 5 line items. I can easily create a query that pulls either the sum or the count by themselves, but when I created my query with both, I end up with numbers that are multipled versions of what I want. I believe it is multiplying my piece counts and dollar values.
SELECT DISTINCTROW tblPO.CompanyName, tblPO.ShopOrderNo, tbl.OrderDate, Sum(tblPODescriptions.ItemAmount) AS SumOfItemAmount, Count(tblCostSheets.Description) AS CountOfDescription
FROM (tblPO INNER JOIN tblPODescriptions ON (tblPO.CompanyName = tblPODescriptions.CompanyName) AND (tblPO.PurchaseOrderNo = tblPODescriptions.PurchaseOrderNo) AND (tblPO.PODate = tblPODescriptions.PODate)) INNER JOIN tblCostSheets ON tblPO.ShopOrderNo = tblCostSheets.ShopOrderNo
GROUP BY tblPO.CompanyName, tblPO.ShopOrderNo, tblPO.OrderDate
HAVING (((tblPO.OrderDate) Between [Enter Start Date:] And [Enter End Date:]));

Sum of distinct values in field SSRS 2005

I'm working on SSRS report builder that is using a dataset calling a SQL Server 2000 database.
The query is getting sums of a few different fields and is also pulling out all records that have to do with that client number. I want to get the sum of the sum but it is way over because of the detail rows. Basically what I want is the sum of the distinct sum column values.
=Sum(Fields!tot.Value, "table1_Group3")
I saw that you can get sums by the groups and I tried the expression above but it comes back with an error:
The Value expression for the textbox 'tot' has a scope parameter that is not
valid for an aggregate function...
table1_Group3 is the name of the group that holds the sum value in the report.
Any suggestions on how to get the distinct values to sum them in this report.
=Sum(Fields!tot.Value, "table1_Group3")
The code above will give you the sum of "tot" for all rows in the current "table1_Group3." This means that this expression only makes sense somewhere within table1_Group3. Otherwise, SSRS doesn't know which is the current instance of that group.
Sounds like you would like to sum this value across multiple groups, but only take one "tot" from each instance of the group. (Are you sure that all rows in that group will have the same "Tot?")
If tot is the total of other fields in your returned data, then simply add those up in your formula. This may have the added benefit of simplifying your SQL query as well.
Some other options that could work:
- Change your SQL query so that only one row per group gets the Tot field set.
- Use Embedded code in the report to keep a running total which is added to only once per group, such as in the group header.
(If upgrading to 2008R2 SSRS is an option, then the Lookup function could be used here, maybe even to look back at the same dataset.)
change the query/ dataset to sum(distinct tot) using the temp table on the sql server
I suppose you need to write sum(distinct columnName).