views:

1377

answers:

1

I would like to have a chart in SQL Server Reporting Services 2008 show the top X values and sum/group the rest as other. Is this possible without doing the grouping in T-SQL?

Example:

A query brings back the total sales from 50 US states. I want to show the five states that have the most sales and group the rest as "All Other States" with the sum of their sales.

Users will be able to filter by any number of states and I need the chart to show the top 5 of those selected.

I would like to cache the execution of the report for all states and have the report rendered from the snapshot.

+1  A: 

The easiest way to do this is in the SQL itself. Given that you want to run the report off cached data, this isn't an option.

The next obvious way to do it is to do it in custom code. You might do something like the following:

Right-click on the Layout space choose Properties and click on the Code tab. Put in the following code:

Public Dim RowCount As Integer = 0
Public Dim Top5Sum As Double = 0

Public Function HideThisRow(Value As Double) As Boolean
  RowCount = RowCount + 1
  if RowCount > 5 Then
    Return True
  Else
    Top5Sum = Top5Sum + Value
    Return False
  End If
End Function

On the Detail band, make two detail rows - the first is your normal row where you sum the field with the Visibility-Hidden property of this detail row having this expression:

=Code.HideThisRow(Fields!YourFieldToSum.Value)

This will execute the code above as it prepares to display each detail row and hide all rows except the top 5. It also has the side effect of summing the top 5 values.

The second row in your Detail band is where we will display the "All Other States" section so give it the description "All Other States" in the column you have the state's name and in the column that you are displaying your field have the expression:

=Sum(Fields!YourFieldToSum.Value) - Code.Top5Sum

We also have to hide this row for all rows except the last row displayed (row 5), so we make its Visibility-Hidden property be the following expression:

=IIF(RowNumber(Nothing) = 5, False, True)

This effectively hides this row for all rows except the last row to be displayed (row 5).

You'd think you could just do this in the footer of the report rather than doing all this hiding of rows but there is a trap - you can not predict the order in which the report will be built and thus the order in which your code will execute. Really.

If you just did the report with the calculation in the footer rather than in a hidden detail row, then the value of the Top5Sum variable will be calculated appropriately. However, the Visibility-Hidden function will not work (at least on my version of SSRS - it produced 17 blank pages in my test before producing the accurate footer). However, let's say you want to calculate the percentage that each state has and so you add the following expression into your Detail band:

=Fields!YourFieldToSum.Value / SUM(Fields!YourFieldToSum.Value)

This is a perfectly reasonable thing to do, but this completely changes the order in which the report is calculated - in this instance the Detail band needs to know the sum of the field and so the Footer band is calculated before the Detail band is, meaning that the Top5Sum variable is zero at the time the Footer band is calculated and your calculation does not work. However, the Detail rows are now hidden appropriately.

This is why you need to do the calculation in the Detail band and hide all other results rather than doing it in the Footer band as seems logical.

Chris Latta