Upload
others
View
6
Download
1
Embed Size (px)
Citation preview
Report Calculations:
SSRS Source Query
vs Expressions
SQL Saturday #70 – Columbia, SC
3/19/2011
Melissa Coates
Melissa Coates
Blog: http://www.sqlchick.com
Twitter: @sqlchick
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
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 (cont’d)
SSMS
object
explorer:
SSMS
query:
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,
but returns a single summarizing
value.
Sum, Avg, Min, Max, Count
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
Part I:
Aggregate
Functions
Running Value
Average
Count
Calculating
Running Values
Running Value: Functions Available
T-SQL:
No built-in function.
Various options to handle
including:
CTE
Correlated subquery
Self join
Cross join
Temp table
etc…
SSRS:
Syntax:
=RunningValue(expression, function, scope)
Example:
=RunningValue(Fields!SalesAmount.Value, Sum,
"ResellerSalesByYear")
A running aggregate of all non-null numeric values specified by the expression,
evaluated for the given scope.
Running Value: T-SQL Dataset query: Report body:
Report results:
Running Value: SSRS Dataset query: Report body:
Report results:
Running Value T-SQL:
SSRS:
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.
Execution Log:
Execution Log:
SSRS
Average
Average: Functions Available
T-SQL:
SELECT AVG(Amount) or
SELECT AVG(ALL Amount)
SSRS:
=Avg(Fields!Amount.Value)
Average a numeric value, excluding nulls:
T-SQL:
SELECT AVG(DISTINCT Amount)
SSRS:
Not supported
Average distinct, non-null, rows:
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 Dataset query:
Report body:
Report results:
Without
doing
anything
special, we
see the
decimals
when the
averaging
occurs in
SSRS.
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).
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
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.
An “average of an “average” is not usually the correct result.
Correct
(was calculated from detail)
Incorrect
(was calculated from average)
Average Usually we want to average in the source query to
avoid bringing back extra data we don’t need in the
report.
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.
T-SQL
SSRS
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).
Counts
Count: Functions Available
T-SQL:
SELECT COUNT(ALL Size)
SSRS:
=Count(Fields!Size.Value)
Count all rows, excluding nulls:
T-SQL:
SELECT COUNT(*)
SSRS:
=CountRows()
Count all rows, including nulls and duplicates:
T-SQL:
SELECT COUNT(DISTINCT Size)
SSRS:
=CountDistinct(Fields!Size.Value)
Count distinct, non-null, rows: The only Distinct function
available in SSRS
Count: T-SQL Dataset query: Report body:
Report results:
Count: SSRS Dataset query: Report body:
Report results:
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.
Count T-SQL:
SSRS:
Execution Log:
Profiler:
Execution Log:
Profiler:
T-SQL
SSRS
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 drill-
down) then counting in the report is okay to do.
Part II:
Text & Formatting Functions
Return part of string
Trim trailing spaces
String comparisons
Formatting
Text (String) Functions Available
T-SQL:
SUBSTRING(SalesOrderNumber, 3,5)
LEFT(SalesOrderNumber, 2)
RIGHT(SalesOrderNumber, 5)
SSRS:
=Mid(Fields!SalesOrderNumber.Value, 3,5)
=Left(Fields!SalesOrderNumber.Value, 2)
=Right(Fields!SalesOrderNumber.Value, 5)
Return part of a string:
T-SQL:
LTRIM(SalesOrderNumber)
RTRIM(SalesOrderNumber)
RTRIM(LTRIM(SalesOrderNumber))
SSRS:
=LTrim(Fields!SalesOrderNumber.Value)
=RTrim(Fields!SalesOrderNumber.Value)
=Trim(Fields!SalesOrderNumber.Value)
Trim trailing spaces:
Text (String) Functions Available
T-SQL:
SELECT SOUNDEX(
EnglishCountryRegionName)
SELECT DIFFERENCE(
EnglishCountryRegionName,
SpanishCountryRegionName)
SSRS:
=StrComp(
Fields!EnglishCountryRegionName.Value,
Fields!SpanishCountryRegionName.Value, 1)
Results: 0: same
1: string 1 > string 2
-1: string 1 < string 2
String Comparisons: 1: textual comparison (case
insensitive)
0 or skipped: binary comparison
Formatting Functions Available
T-SQL:
CAST(SalesAmount AS Dec(8,2))
CONVERT(DEC(8,2),SalesAmount)
SSRS:
=Format(Fields!SalesAmount.Value, "F2")
=Format(Fields!SalesAmount.Value, "##.##")
Two decimal places – no commas:
T-SQL:
Not supported in T-SQL
SSRS:
=FormatNumber(Fields!SalesAmount.Value, 2)
=Format(Fields!SalesAmount.Value, "#,#.##")
Two decimal places – with commas:
T-SQL:
Not supported in T-SQL
SSRS:
=FormatCurrency(Fields!SalesAmount.Value, 2)
=Format(Fields!SalesAmount.Value, "C2")
Two decimal places – with currency symbol:
.NET codes are
supported
Formatting Functions Available
T-SQL:
Not supported in T-SQL.
SSRS:
=FormatPercent(Fields!SalesPct.Value)
Percentage:
DateTime:
SSRS:
Text & Formatting Functions
SSRS
This is what SSRS is meant for!
Part III:
DateTime Functions
DATEPART
DATEADD
Current Date and Time
DateTime Functions Available
T-SQL:
SELECT DATEPART(YY,ModifiedDate)
SELECT DATEADD(DAY,2,OrderDate)
SSRS:
=DatePart(DateInterval.Year,
Fields!ModifiedDate.Value)
=DateAdd(DateInterval.Day, 2,
Fields!ModifiedDate.Value)
DATEPART and DATEADD:
Year Minute
Quarter Second
Month Millisecond
Week Microsecond
Day Nanosecond
Hour
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
SSRS
T-SQL is more precise.
SSRS is well formatted more closely
for presentation.
Part IV:
Program Flow
Functions
CASE
IIF
Switch
Decoding Values
Decoding Values
SSRS: =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"))))
Evaluates a list of conditions and returns one of multiple possible result expressions:
T-SQL:
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
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
SSRS:
=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
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.
T-SQL
SSRS
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.
Part V:
Miscellaneous
Functions
Ranking
Row Number
Previous
Percent of Total
Scoping
Scoping in SSRS
Scope may be specified as any of these (using the Name property):
Dataset (i.e., the query - after filters are applied)
Data Region (i.e., table, matrix, list, etc)
• May the outer data region, or a nested data region
Group
• 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
Specifies what data to include in aggregate calculations.
How would
you
implement
this concept
in T-SQL?
Scoping in T-SQL Specifies what field(s) to group by in aggregate calculations.
Scoping
Handled using the OVER() clause; result sets
are divided using PARTITION statements.
T-SQL
SSRS
A little more straightforward to do within SSRS,
especially when source queries get more complex.
Scoping permitted for:
Dataset
Data Region
Group
Ranking & Row Numbers
Ranking: Functions Available
T-SQL: RANK() OVER (ORDER BY a.PostalCode)
SSRS: Not supported
Rank of each row within the partition:
T-SQL: DENSE_RANK() OVER (ORDER BY a.PostalCode)
SSRS: Not supported
Rank of each row within the partition, without any gaps in numbering:
T-SQL: NTILE(4) OVER (ORDER BY a.PostalCode)
SSRS: Not supported
Distribute rows into a specified number of groups:
T-SQL: ROW_NUMBER() OVER(ORDER BY SalesYTD DESC)
or
ROW_NUMBER() OVER(PARTITION BY PostalCode
ORDER BY SalesYTD DESC)
SSRS: =RowNumber(“Dset_YTDSales”)
or
=RowNumber(“Group_PostalCode”)
Sequential number of each row:
Ranking and RowNumber: T-SQL
RowNumber: SSRS Dataset query:
Report body:
Report results:
Ranking
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.
T-SQL
SSRS The RowNumber function in SSRS does very
nicely when it’s scoped, although the same thing
could be done in T-SQL with partitions.
Percent of Total
Percent of Total: Functions Available
T-SQL:
No built-in function.
Various options to handle
including:
Common table expression
Correlated subquery
Self-join
Cross-join
etc…
SSRS:
No built-in function. Handled gracefully, however,
using scoping in SSRS.
Example:
=FormatPercent(
Sum(Fields!SalesAmount.Value)
/
Sum(Fields!SalesAmount.Value,"Tablix1")
,1)
scope
A running aggregate of all non-null numeric values specified by the expression,
evaluated for the given 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:
SSRS:
SSRS function: easier to implement.
This isn’t a calculation that is likely to change, so it’s
okay to embed in report.
Execution Log:
Execution Log:
SSRS
Previous Row
Previous Row: Functions Available
T-SQL:
No built-in function.
Various options to handle
including:
Common table expression
Correlated subquery
Self join
Cross join
Temp table
etc…
SSRS:
=Previous(Fields!SalesAmount.Value)
Finding a value from the previous row:
Previous Row: T-SQL Dataset query: Report body:
Report results:
Previous Row: SSRS Dataset query: Report body:
Report results:
Previous Row T-SQL:
SSRS:
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.
Execution Log:
Execution Log:
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 Why?
Decoding Values
(CASE vs IIF vs Switch)
Centralize logic
Misc. Function 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