Report Calculations: SSRS Source Query vs Expressions SQL Saturday #70 – Columbia, SC 3/19/2011 Melissa Coates About Me • Melissa is a Business Intelligence developer based in Charlotte, NC • Consultant with Mariner, specializing in BI and Data Warehousing solutions using the Microsoft platform • MCITP and MCTS in BI Melissa Coates Blog: http://www.sqlchick.com Twitter: @sqlchick About Mariner http://www.mariner-usa.com Other Presentations Today Who Topic Time Bill Pearson Design and Implement BI Like Edison 9:45 am Bill Pearson Entity Strategies: Structuring Your Consultancy 1:15 pm Melissa Coates Report Calculations: SSRS Source Query vs. Expressions 1:15 pm Wayne Snyder Information: Are You Blinded by the Light? 2:30 pm Javier Guillen DAX Formulas: Evaluation Context 3:45 pm Agenda Overview: Terms & Types of Functions Compare several functions between T-SQL and SSRS Syntax Report impact Differences in functionality Differences in results returned Goal for Today Identify common situations when performing calculations within SSRS is preferred, versus when T-SQL is more appropriate Scope of Discussion • Source query: SQL Server relational data sources • SSRS functions: expressions within a text box • We won’t be extending this discussion to custom code • Performance statistics shown are from my laptop (Dell Latitude, 64-bit, Windows 7, 2.53GHz, 8GB RAM) Examples • Most examples use AdventureWorksDW2008R2 • A few use AdventureWorks2008R2 Concerns of a Report Developer Concerns of a Report Developer Accuracy Performance Maintenance Reusability Standardization Security Testing Deployment Documentation ....etc Managing “Hefty” Calculations 1st choice: Calculations are predefined in the source data (ex: handled by ETL) 2nd choice: Calculations are centralized in a reusable stored procedure or function within the database 3rd choice: Calculations are centralized in an SSRS source query (R2 makes this easier with shared datasets) 4th choice: Calculations are embedded within expressions inside an individual report Overview: Terms & Types of Functions Function A portion of code which performs a specific task In other languages, called a procedure, method, or subroutine Functions can be built-in, or user-defined In T-SQL, functions are usually used to query the data, or perform operations on data MSDN: Function SSMS query: SSMS object explorer: (cont’d) Expression In T-SQL, expressions are: A combination of symbols and operators which are evaluated to return a single data value. **In T-SQL: the expression is evaluated individually for each row in the result set.** An expression may or may not contain a function. Simple expressions can be a single constant, variable, column, or scalar function. Operator symbols can be used to join 2 or more simple expressions into a complex expression. In SSRS, expressions are: Written in VB.Net Refers to constants, operators, functions, fields, collections, variables, and/or custom code 4 Types of T-SQL Functions Type Description Examples Rowset Returns object that can be used like table references in a SQL statement. OpenRowset, OpenQuery Ranking Returns a ranking value for each row in a partition. Rank, Ntile, Row_Number Aggregate Operates on a collection of values, Sum, Avg, Min, Max, Count but returns a single summarizing value. Scalar Operates on a single value, and also returns a single value. Scalar values are used wherever an expression is valid. Includes: • Date and Time functions • Mathematical functions • String functions ….among many others GetDate, DatePart, DateDiff, Abs, Round, Case, Cast, Convert, Lower, Upper, Len, LTrim, RTrim 9 Types of SSRS Functions Type Description Examples Aggregate Summarize values for a set of non-null numeric data Avg, Count, First, Last, Sum Text Operates on a textual (string) value FormatNumber, Join, Replace, StrComp, RTrim, UCase Date & Time Operates on date and time values DateAdd, DateDiff, FormatDateTime, Now, Today Program Flow Conditional logic Choose, IIF, Switch Misc Miscellaneous InScope, Level, Lookup, LookupSet, MultiLookup, Previous, RowNumber Financial Calculates numeric values Pmt, Rate, FV, DDB Math Calculates numeric values Abs, Ceiling, Rnd Inspection Inspects the value & returns info about it IsNothing, IsDate, IsArray, IsNumeric Conversion Converts to another data type CInt, CDec, CChar Cheat Sheet: Comparisons Between T-SQL Functions and SSRS Functions Cheat Sheet Available at: http://www.sqlchick.com Presentations page Part I: Aggregate Functions Running Value Average Count Calculating Running Values Running Value: Functions Available A running aggregate of all non-null numeric values specified by the expression, evaluated for the given scope. T-SQL: SSRS: No built-in function. Syntax: =RunningValue(expression, function, scope) Various options to handle including: CTE Correlated subquery Self join Cross join Temp table etc… Example: =RunningValue(Fields!SalesAmount.Value, Sum, "ResellerSalesByYear") Running Value: T-SQL Dataset query: Report body: Report results: Running Value: SSRS Dataset query: Report body: Report results: Running Value T-SQL: Execution Log: SSRS: Execution Log: SSRS function: easier to implement. SSRS function: more performant. This isn’t a calculation that is likely to change, so it’s okay to embed in report. SSRS Average Average: Functions Available Average a numeric value, excluding nulls: T-SQL: SSRS: SELECT AVG(Amount) or SELECT AVG(ALL Amount) =Avg(Fields!Amount.Value) Average distinct, non-null, rows: T-SQL: SSRS: SELECT AVG(DISTINCT Amount) Not supported Average: T-SQL Dataset query: Report body: Report results: ReorderPoint is an integer field. Even if we format the report results as decimal(2), we don’t get decimals because T-SQL averaged the integer. Average: SSRS Report body: Dataset query: Report results: This query returns detail rows – which is okay if we’re going to show the detail on the report (i.e., drill-down +/- on the right). Without doing anything special, we see the decimals when the averaging occurs in SSRS. Average: T-SQL – Averaging an Integer Dataset query: This example is using an integer field. If we cast to a decimal first, we can see the decimals within the report results. This is an extra step in T-SQL though. Average: Aggregating an Aggregate An “average of an “average” is not usually the correct result. Averaged in T-SQL Averaged in SSRS: results in an “average of an average” which returns a very different result than if all detail rows were averaged. Incorrect (was calculated from average) Correct (was calculated from detail) Average Usually we want to average in the source query to avoid bringing back extra data we don’t need in the report. T-SQL If the field being averaged is an integer, and you want to see accurate decimal places, cast it first before it’s averaged. If you need a distinct Avg: this must be done in the source query. If you need the detail in the report anyway (ex: a drill-down) then averaging in the report is okay & might even save a cast operation. When detail is present, SSRS is really good at averaging per groups, and for the grand total. Careful with performing an aggregate of an aggregate (if underlying detail isn’t in the report query). SSRS Counts Count: Functions Available Count all rows, excluding nulls: T-SQL: SSRS: SELECT COUNT(ALL Size) =Count(Fields!Size.Value) Count all rows, including nulls and duplicates: T-SQL: SSRS: SELECT COUNT(*) =CountRows() Count distinct, non-null, rows: The only Distinct function available in SSRS T-SQL: SSRS: SELECT COUNT(DISTINCT Size) =CountDistinct(Fields!Size.Value) Count: T-SQL Dataset query: Report body: Report results: Count: SSRS Dataset query: This query returns all rows for no other purpose than to aggregate them – i.e., unnecessary detail – this is typically not the most optimal solution. Report body: Report results: Count T-SQL: Profiler: Execution Log: SSRS: Profiler: Execution Log: T-SQL Usually we want to count in the source query to avoid bringing back extra data we don’t need in the report. If you need the detail in the report anyway (ex: a drilldown) then counting in the report is okay to do. SSRS Part II: Text & Formatting Functions Return part of string Trim trailing spaces String comparisons Formatting Text (String) Functions Available Return part of a string: T-SQL: SSRS: SUBSTRING(SalesOrderNumber, 3,5) =Mid(Fields!SalesOrderNumber.Value, 3,5) LEFT(SalesOrderNumber, 2) =Left(Fields!SalesOrderNumber.Value, 2) RIGHT(SalesOrderNumber, 5) =Right(Fields!SalesOrderNumber.Value, 5) Trim trailing spaces: T-SQL: SSRS: LTRIM(SalesOrderNumber) =LTrim(Fields!SalesOrderNumber.Value) RTRIM(SalesOrderNumber) =RTrim(Fields!SalesOrderNumber.Value) RTRIM(LTRIM(SalesOrderNumber)) =Trim(Fields!SalesOrderNumber.Value) Text (String) Functions Available String Comparisons: 1: textual comparison (case insensitive) 0 or skipped: binary comparison T-SQL: SSRS: SELECT SOUNDEX( EnglishCountryRegionName) =StrComp( Fields!EnglishCountryRegionName.Value, Fields!SpanishCountryRegionName.Value, 1) SELECT DIFFERENCE( EnglishCountryRegionName, SpanishCountryRegionName) Results: 0: same 1: string 1 > string 2 -1: string 1 < string 2 Formatting Functions Available .NET codes are supported Two decimal places – no commas: T-SQL: SSRS: CAST(SalesAmount AS Dec(8,2)) CONVERT(DEC(8,2),SalesAmount) =Format(Fields!SalesAmount.Value, "F2") =Format(Fields!SalesAmount.Value, "##.##") Two decimal places – with commas: T-SQL: SSRS: Not supported in T-SQL =FormatNumber(Fields!SalesAmount.Value, 2) =Format(Fields!SalesAmount.Value, "#,#.##") Two decimal places – with currency symbol: T-SQL: SSRS: Not supported in T-SQL =FormatCurrency(Fields!SalesAmount.Value, 2) =Format(Fields!SalesAmount.Value, "C2") Formatting Functions Available Percentage: T-SQL: SSRS: Not supported in T-SQL. =FormatPercent(Fields!SalesPct.Value) DateTime: SSRS: Text & Formatting Functions This is what SSRS is meant for! SSRS Part III: DateTime Functions DATEPART DATEADD Current Date and Time DateTime Functions Available DATEPART and DATEADD: T-SQL: SSRS: SELECT DATEPART(YY,ModifiedDate) =DatePart(DateInterval.Year, Fields!ModifiedDate.Value) SELECT DATEADD(DAY,2,OrderDate) =DateAdd(DateInterval.Day, 2, Fields!ModifiedDate.Value) Year Quarter Month Week Day Hour Minute Second Millisecond Microsecond Nanosecond SSRS: precision down to the second T-SQL: more precise DateTime Functions Available Current Date and Time: T-SQL Function Returns SELECT GETDATE() 2011-02-22 19:10:47.757 SELECT CURRENT_TIMESTAMP 2011-02-22 19:10:47.757 SELECT SYSDATETIME() 2011-02-22 19:10:47.7582404 SSRS Function Returns =Now() 2/22/2011 7:10:47 PM =Globals!ExecutionTime 2/22/2011 7:10:47 PM =Today() 2/22/2011 12:00:00AM =DateString() 02-22-2011 =TimeString() 19:10:47 DateTime Functions T-SQL T-SQL is more precise. SSRS is well formatted more closely for presentation. SSRS Part IV: Program Flow Functions CASE IIF Switch Decoding Values Decoding Values Evaluates a list of conditions and returns one of multiple possible result expressions: T-SQL: SSRS: Simple CASE (allows equality check only) CASE ProductLine WHEN 'R' THEN 'Road' WHEN 'M' THEN 'Mountain' WHEN 'T' THEN 'Touring' WHEN 'S' THEN 'Other' ELSE 'Not for sale' END AS Category =IIF(Fields!ProductLine.Value = "R","Road", IIF(Fields!ProductLine.Value = "M","Mountain", IIF(Fields!ProductLine.Value = "T","Touring", IIF(Fields!ProductLine.Value = "S","Other", “Not For Sale")))) SSRS: Searched CASE: CASE WHEN ProductLine = 'R' THEN 'Road' WHEN ProductLine = 'M' THEN 'Mountain' WHEN ProductLine = 'T' THEN 'Touring' WHEN ProductLine = 'S' THEN 'Other' ELSE 'Not for sale' END AS Category =Switch( TRIM(Fields!ProductLine.Value) = "R","Road", TRIM(Fields!ProductLine.Value) = "M","Mountain", TRIM(Fields!ProductLine.Value) = "T","Touring", TRIM(Fields!ProductLine.Value) = "S","Other", IsNothing(Fields!ProductLine.Value),“Not For Sale" ) Decoding Values T-SQL The appeal of adding the Case statement to the T-SQL source query is that there’s probably some logic there – and it’s nice to centralize it where it’s readily apparent. Switch is equivalent to a Searched CASE (i.e., can handle various operators). Usually easier to read than a nested IIF. Switch is “finicky” & needs a Trim, else it may fail to find a match on a varchar field (whereas the IIF isn’t finicky – it works like the T-SQL case). There’s not an “ELSE” in a Switch, so might want to embed Switch within IIF. SSRS Part V: Miscellaneous Functions Ranking Row Number Previous Percent of Total Scoping Scoping in SSRS Specifies what data to include in aggregate calculations. Scope may be specified as any of these (using the Name property): Dataset (i.e., the query - after filters are applied) How would Data Region (i.e., table, matrix, list, etc) you • May the outer data region, or a nested data region implement this concept Group in T-SQL? • If a table: these are the Row and Column Groups • If a chart: these are the Series and Category Groups • May be groups for an outer data region, or a nested data region Nothing • Uses the outermost Data Region scope available to the report item Scoping in T-SQL Specifies what field(s) to group by in aggregate calculations. Scoping T-SQL Handled using the OVER() clause; result sets are divided using PARTITION statements. A little more straightforward to do within SSRS, especially when source queries get more complex. Scoping permitted for: Dataset Data Region Group SSRS Ranking & Row Numbers Ranking: Functions Available Rank of each row within the partition: T-SQL: SSRS: RANK() OVER (ORDER BY a.PostalCode) Not supported Rank of each row within the partition, without any gaps in numbering: T-SQL: SSRS: DENSE_RANK() OVER (ORDER BY a.PostalCode) Not supported Distribute rows into a specified number of groups: T-SQL: SSRS: NTILE(4) OVER (ORDER BY a.PostalCode) Not supported Sequential number of each row: T-SQL: SSRS: ROW_NUMBER() OVER(ORDER BY SalesYTD DESC) or ROW_NUMBER() OVER(PARTITION BY PostalCode ORDER BY SalesYTD DESC) =RowNumber(“Dset_YTDSales”) or =RowNumber(“Group_PostalCode”) Ranking and RowNumber: T-SQL RowNumber: SSRS Report body: Dataset query: Report results: Ranking T-SQL If you need to do a Rank or an NTile, you must do it within the source query. Rank Dense_Rank NTile Both scenarios can handle Row Numbers through Scope or Partitions. The RowNumber function in SSRS does very nicely when it’s scoped, although the same thing could be done in T-SQL with partitions. SSRS Percent of Total Percent of Total: Functions Available A running aggregate of all non-null numeric values specified by the expression, evaluated for the given scope. T-SQL: SSRS: No built-in function. No built-in function. Handled gracefully, however, using scoping in SSRS. Various options to handle including: Common table expression Correlated subquery Self-join Cross-join etc… Example: =FormatPercent( Sum(Fields!SalesAmount.Value) / Sum(Fields!SalesAmount.Value,"Tablix1") ,1) scope Percent of Total: T-SQL Dataset query: Report body: Report results: Percent of Total: SSRS Dataset query: Report body: Report results: Percent of Total T-SQL: Execution Log: SSRS: Execution Log: SSRS function: easier to implement. This isn’t a calculation that is likely to change, so it’s okay to embed in report. SSRS Previous Row Previous Row: Functions Available Finding a value from the previous row: T-SQL: SSRS: No built-in function. =Previous(Fields!SalesAmount.Value) Various options to handle including: Common table expression Correlated subquery Self join Cross join Temp table etc… Previous Row: T-SQL Dataset query: Report body: Report results: Previous Row: SSRS Dataset query: Report body: Report results: Previous Row T-SQL: Execution Log: SSRS: Execution Log: SSRS function: easier to implement. SSRS function: more performant. This isn’t a calculation that is likely to change, so it’s okay to embed in report. SSRS Conclusion Recap Aggregate Function T-SQL SSRS Why? Running Value Built-in to SSRS Average & Count Depends on level of detail Text Function T-SQL SSRS Why? Return part of string Same functionality Trim trailing spaces Trim both in 1 step String comparisons Quick & easy Formatting Far more functionality; intended to be done in report Recap (cont’d) DateTime Function T-SQL SSRS Why? DatePart and DateAdd More precision Current Date Same; formatted nicely Program Flow Function T-SQL SSRS Decoding Values (CASE vs IIF vs Switch) Misc. Function Why? Centralize logic T-SQL SSRS Why? Ranking & Row Nbr A lot more functionality Percent of Total Easy to do with scope Previous Row Built-in to SSRS When Is SSRS Preferred? • If you need to “Scope” the calculation (a little more • • • • • • • • straightforward than the Partitioning in T-SQL) RunningValue (no built-in equivalent in T-SQL) Previous (no built-in equivalent in T-SQL) Percent of Total Handling formatting Trim (can do a Trim of left & right with one step) String Comparisons (StrComp is very useful) Lookups to another dataset First and Last When Is Source Query Preferred? • When you can centralize the logic (and SSRS would • • • • duplicate or need to be done multiple times) Aggregations, such as counting and averaging (can often omit unneeded detail being sent to the report) Ranking Distinct (exception: CountDistinct) User-Defined Functions Questions & Suggestions References Built-In Functions (Transact-SQL): http://msdn.microsoft.com/en-us/library/ms174318.aspx Expressions (Transaction-SQL): http://msdn.microsoft.com/en-us/library/ms190286.aspx Understanding Expression References (SSRS): http://msdn.microsoft.com/en-us/library/cc281391(v=SQL.100).aspx Using Built-In Report and Aggregate Functions in Expressions (SSRS): http://msdn.microsoft.com/en-us/library/ms159673.aspx http://technet.microsoft.com/en-us/library/ms159673(SQL.100).aspx Understanding Expression Scope for Totals, Aggregates, and Built-In Collections (SSRS): http://technet.microsoft.com/en-us/library/dd255256.aspx Expression Examples (SSRS): http://technet.microsoft.com/en-us/library/ms157328.aspx Calculating Totals and Other Aggregates (SSRS): http://technet.microsoft.com/en-us/library/bb630415.aspx You might also like … To register: https://www.clicktoattend.com/ invitation.aspx?code=154140 or http://www.mariner-usa.com Link to the Event will be at bottom right of home page Thanks for attending! Melissa Coates Blog: http://www.sqlchick.com Twitter: @sqlchick Don’t forget to download the cheat sheet! Creative Commons License: Attribution-NonCommercial-NoDerivative Works 3.0
© Copyright 2026 Paperzz