Edit

Simplifying and improving your SQL with

CTE’s and Windowing Functions

Clayton Groom

11/15/2013
t: cgroom or SQLMonger
cgroom@mailctp.com
www.geekswithblogs.net/sqlmonger
http://www.linkedin.com/in/claytongroom/
Platinum
Sponsors

Gold
Sponsors

Silver Sponsors
Agenda
SQL Basics
Think in Sets
Baseline performance
Save EVERYTHING as you develop (WIP)
Learn what is new and refactor old code

Examples/Scenarios
Begin with the end in mind
–

An example

Common Table Expressions
Windowing functions’

Questions?
Objective
Introduce you to new T-SQL language features you are probably not using…

Think in sets
Get your feet wet with new T-SQL functionality
Common Table Expressions (CTE’s)
Windowing functions
Teach SQL-only techniques for aggregation
Rolling aggregates
MTD, QTD, YTD, Same Period PY, etc.

4
Think in Sets
Improve your SQL Skills to improve your applications
Procedural approaches are out
– Cursors should almost never be used
– Existing cursor can be “fixed” by changing to the best cursor
type for the situation.
Diagram your queries before you write them
– Venn
– Tree
Set based approaches include:
– Correlated sub queries
– Common Table Expressions (CTE’s)
– MERGE operator
– Outer Apply
5
Think in Sets
Some great authors…

6
SQL Development 101
Baseline performance
Use DBCC FREEPROCCACHE to clear the procedure cache and
provide solid baseline results
Use Statistics IO and Statistics Time to capture query stats.
SET STATISTICS IO ON;
SET STATISTICS TIME ON;

Keep versions of your code, with timings
– Database performance will change as data grows
– Having the options you have already tried available
– May be applicable to different situations

7
Common Table Expressions (CTE’s)
ANSI standard way to avoid temp tables

CTE’s are table results objects defined within the scope of a single
statement.
• Use CTE’s in place of Temp tables
• Aggregate results for following steps
• Use CTE to substitute for a VIEW or #temp table
• Enable GROUP BY on derive columns
• Support Recursive joins
• More readable, easier to maintain code – building block approach.
Limitations:
• GROUP BY, HAVING, or aggregate functions are not allowed in the recursive
part of a recursive common table expression
•

Outer joins are not allowed in the recursive part of a recursive common
table expression
8
CTE Example
Simple example – Calculate Total and Percent of Total
WITH CTE_Totals
AS (SELECT CustomerKey
,SUM(SalesAmount) AS [Total Cust Sales Amt]
FROM [dbo].[FactInternetSales]
WHERE CustomerKey IN (15954, 27052, 23808)
GROUP BY CustomerKey
)
SELECT f.CustomerKey
, f.ProductKey
, f.SalesAmount
,t.[Total Cust Sales Amt]
,f.SalesAmount / t.[Total Cust Sales Amt]
as [Pct of Total]
FROM [dbo].[FactInternetSales] AS f
INNER JOIN CTE_Totals t
ON f.CustomerKey = t.CustomerKey
WHERE f.CustomerKey IN (15954, 27052, 23808)
9
Demo - Common Table Expression
I will post the examples to my SkyDrive and have a link on my Blog. I will be updating the examples
as I come across useful applications. http://sdrv.ms/HZtKYP

10
Windowing functions
Supported Windowing Elements

Function_name(<arguments.) OVER(
[<PARTITION BY clause>]
[<ORDER BY clause>
[<ROW or RANGE clause>] ] )

11
Windowing function Example
Simple example – Calculate Total and Percent of Total
SELECT CustomerKey
,ProductKey
,SalesAmount
,SUM(SalesAmount)
OVER(PARTITION BY CustomerKey)
AS [Cust Sales Amt]
,SUM(SalesAmount)
OVER() AS [Total Sales Amt]
,cast(100.0 * SalesAmount/SUM(SalesAmount)
OVER(PARTITION BY CustomerKey)
as numeric(5,2)) as [Pct of Cust Total]
,cast(100.0 * SalesAmount/SUM(SalesAmount)
OVER()
as numeric(5,2)) as [Pct of Total]
FROM [dbo].[FactInternetSales]
WHERE CustomerKey IN (15954, 27052, 23808)
order by 1,2;
12
Window Partition Clause
Sets the “frame” or subset of the rows that will be accessible to the
windowing function

13
Window Order Clause
Orders the rows within the Partitioning frame
Required for the ROW and RANGE operators

14
Window Framing Clause
Selects rows within a frame, relative to the current row
Requires an ORDER BY clause
sum(sum(f.SalesAmount) )
OVER(PARTITION BY f.productkey, year(f.orderdate),
Month(f.orderdate)
ORDER BY f.productkey, f.orderdate
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) as [Sales Amt MTD]
4
Unbounded
Preceding

3

2

1

0

1

Current
Row

2

3
Unbounded
Following

15
Window Framing Clause
Supported Options
ROWS UNBOUNDED PRECEDING
ROWS <unsigned integer literal> PRECEDING
ROWS CURRENT ROW
ROWS BETWEEN UNBOUNDED PRECEDING AND <unsigned integer literal> PRECEDING
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
ROWS BETWEEN UNBOUNDED PRECEDING AND <unsigned integer literal> FOLLOWING
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
ROWS BETWEEN <unsigned integer literal> PRECEDING AND <unsigned integer literal> PRECEDING
ROWS BETWEEN <unsigned integer literal> PRECEDING AND CURRENT ROW
ROWS BETWEEN <unsigned integer literal> PRECEDING AND <unsigned integer literal> FOLLOWING
ROWS BETWEEN <unsigned integer literal> PRECEDING AND UNBOUNDED FOLLOWING
ROWS BETWEEN CURRENT ROW AND CURRENT ROW
ROWS BETWEEN CURRENT ROW AND <unsigned integer> FOLLOWING
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
ROWS BETWEEN <unsigned integer literal> FOLLOWING AND <unsigned integer> FOLLOWING
ROWS BETWEEN <unsigned integer literal> FOLLOWING AND UNBOUNDED FOLLOWING
RANGE UNBOUNDED PRECEDING
RANGE CURRENT ROW
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
RANGE BETWEEN CURRENT ROW AND CURRENT ROW

RANGE uses a count of distinct values, where ROWS uses the count of the
rows. Rows with the a “TIE” based on the Order By clause will be merged.
16
Windowing Functions - Aggregate
Aggregate Functions that can be used with the OVER Clause

AVG()
CHECKSUM_AGG() - Checksum of values in a group
COUNT(), COUNT_BIG()
MAX()
MIN()
SUM()
STDEV()
STDEVP()
VAR()
VARP()
17
Windowing Functions - Ranking
Ranking functions

RANK()
DENSE_RANK()
NTILE()
ROW_NUMBER()

-

18
Windowing Functions - Analytic
Analytic functions

CUME_DIST()
FIRST_VALUE()
LAST_VALUE()
LEAD()
LAG()
PERCENTILE_CONT()
PERCENTILE_DISC()
PERCENT_RANK()

- Cumulative Distribution
- First value within the ordered partition
- Last value within the ordered partition
- Returns a following value based on an offset
- Returns a prior value based on an offset
- Percentile based on a continuous distribution
- Percentile based on discreet column values
- Relative rank of a row within a group of rows

19
Other new Functions
Aggregate Functions that can be used with the OVER Clause

GROUPING()
GROUPING_ID()

- Replaces the COMPUTE clause
- And gives us some new capabilities

20
Demonstrations
I will post the examples to my SkyDrive and have a link on my Blog. I will be updating the examples
as I come across useful applications. http://sdrv.ms/HZtKYP

21
References
Windows Functions in SQL
https://www.simple-talk.com/sql/t-sql-programming/window-functions-in-sql/
Working with Window Functions in SQL Server

https://www.simple-talk.com/sql/learn-sql-server/working-with-window-functions-in-sqlserver/
SQL Server 2012 Windowing Functions Part 1 of 2: Running and Sliding Aggregates
http://lennilobel.wordpress.com/tag/t-sql-running-aggregates/
SQL Server Books Online – Over Clause
http://technet.microsoft.com/en-us/library/ms189461.aspx

22
Questions?

Simplifying SQL with CTE's and windowing functions

  • 1.
    Edit Simplifying and improvingyour SQL with CTE’s and Windowing Functions Clayton Groom 11/15/2013 t: cgroom or SQLMonger cgroom@mailctp.com www.geekswithblogs.net/sqlmonger http://www.linkedin.com/in/claytongroom/
  • 2.
  • 3.
    Agenda SQL Basics Think inSets Baseline performance Save EVERYTHING as you develop (WIP) Learn what is new and refactor old code Examples/Scenarios Begin with the end in mind – An example Common Table Expressions Windowing functions’ Questions?
  • 4.
    Objective Introduce you tonew T-SQL language features you are probably not using… Think in sets Get your feet wet with new T-SQL functionality Common Table Expressions (CTE’s) Windowing functions Teach SQL-only techniques for aggregation Rolling aggregates MTD, QTD, YTD, Same Period PY, etc. 4
  • 5.
    Think in Sets Improveyour SQL Skills to improve your applications Procedural approaches are out – Cursors should almost never be used – Existing cursor can be “fixed” by changing to the best cursor type for the situation. Diagram your queries before you write them – Venn – Tree Set based approaches include: – Correlated sub queries – Common Table Expressions (CTE’s) – MERGE operator – Outer Apply 5
  • 6.
    Think in Sets Somegreat authors… 6
  • 7.
    SQL Development 101 Baselineperformance Use DBCC FREEPROCCACHE to clear the procedure cache and provide solid baseline results Use Statistics IO and Statistics Time to capture query stats. SET STATISTICS IO ON; SET STATISTICS TIME ON; Keep versions of your code, with timings – Database performance will change as data grows – Having the options you have already tried available – May be applicable to different situations 7
  • 8.
    Common Table Expressions(CTE’s) ANSI standard way to avoid temp tables CTE’s are table results objects defined within the scope of a single statement. • Use CTE’s in place of Temp tables • Aggregate results for following steps • Use CTE to substitute for a VIEW or #temp table • Enable GROUP BY on derive columns • Support Recursive joins • More readable, easier to maintain code – building block approach. Limitations: • GROUP BY, HAVING, or aggregate functions are not allowed in the recursive part of a recursive common table expression • Outer joins are not allowed in the recursive part of a recursive common table expression 8
  • 9.
    CTE Example Simple example– Calculate Total and Percent of Total WITH CTE_Totals AS (SELECT CustomerKey ,SUM(SalesAmount) AS [Total Cust Sales Amt] FROM [dbo].[FactInternetSales] WHERE CustomerKey IN (15954, 27052, 23808) GROUP BY CustomerKey ) SELECT f.CustomerKey , f.ProductKey , f.SalesAmount ,t.[Total Cust Sales Amt] ,f.SalesAmount / t.[Total Cust Sales Amt] as [Pct of Total] FROM [dbo].[FactInternetSales] AS f INNER JOIN CTE_Totals t ON f.CustomerKey = t.CustomerKey WHERE f.CustomerKey IN (15954, 27052, 23808) 9
  • 10.
    Demo - CommonTable Expression I will post the examples to my SkyDrive and have a link on my Blog. I will be updating the examples as I come across useful applications. http://sdrv.ms/HZtKYP 10
  • 11.
    Windowing functions Supported WindowingElements Function_name(<arguments.) OVER( [<PARTITION BY clause>] [<ORDER BY clause> [<ROW or RANGE clause>] ] ) 11
  • 12.
    Windowing function Example Simpleexample – Calculate Total and Percent of Total SELECT CustomerKey ,ProductKey ,SalesAmount ,SUM(SalesAmount) OVER(PARTITION BY CustomerKey) AS [Cust Sales Amt] ,SUM(SalesAmount) OVER() AS [Total Sales Amt] ,cast(100.0 * SalesAmount/SUM(SalesAmount) OVER(PARTITION BY CustomerKey) as numeric(5,2)) as [Pct of Cust Total] ,cast(100.0 * SalesAmount/SUM(SalesAmount) OVER() as numeric(5,2)) as [Pct of Total] FROM [dbo].[FactInternetSales] WHERE CustomerKey IN (15954, 27052, 23808) order by 1,2; 12
  • 13.
    Window Partition Clause Setsthe “frame” or subset of the rows that will be accessible to the windowing function 13
  • 14.
    Window Order Clause Ordersthe rows within the Partitioning frame Required for the ROW and RANGE operators 14
  • 15.
    Window Framing Clause Selectsrows within a frame, relative to the current row Requires an ORDER BY clause sum(sum(f.SalesAmount) ) OVER(PARTITION BY f.productkey, year(f.orderdate), Month(f.orderdate) ORDER BY f.productkey, f.orderdate ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) as [Sales Amt MTD] 4 Unbounded Preceding 3 2 1 0 1 Current Row 2 3 Unbounded Following 15
  • 16.
    Window Framing Clause SupportedOptions ROWS UNBOUNDED PRECEDING ROWS <unsigned integer literal> PRECEDING ROWS CURRENT ROW ROWS BETWEEN UNBOUNDED PRECEDING AND <unsigned integer literal> PRECEDING ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ROWS BETWEEN UNBOUNDED PRECEDING AND <unsigned integer literal> FOLLOWING ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ROWS BETWEEN <unsigned integer literal> PRECEDING AND <unsigned integer literal> PRECEDING ROWS BETWEEN <unsigned integer literal> PRECEDING AND CURRENT ROW ROWS BETWEEN <unsigned integer literal> PRECEDING AND <unsigned integer literal> FOLLOWING ROWS BETWEEN <unsigned integer literal> PRECEDING AND UNBOUNDED FOLLOWING ROWS BETWEEN CURRENT ROW AND CURRENT ROW ROWS BETWEEN CURRENT ROW AND <unsigned integer> FOLLOWING ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ROWS BETWEEN <unsigned integer literal> FOLLOWING AND <unsigned integer> FOLLOWING ROWS BETWEEN <unsigned integer literal> FOLLOWING AND UNBOUNDED FOLLOWING RANGE UNBOUNDED PRECEDING RANGE CURRENT ROW RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING RANGE BETWEEN CURRENT ROW AND CURRENT ROW RANGE uses a count of distinct values, where ROWS uses the count of the rows. Rows with the a “TIE” based on the Order By clause will be merged. 16
  • 17.
    Windowing Functions -Aggregate Aggregate Functions that can be used with the OVER Clause AVG() CHECKSUM_AGG() - Checksum of values in a group COUNT(), COUNT_BIG() MAX() MIN() SUM() STDEV() STDEVP() VAR() VARP() 17
  • 18.
    Windowing Functions -Ranking Ranking functions RANK() DENSE_RANK() NTILE() ROW_NUMBER() - 18
  • 19.
    Windowing Functions -Analytic Analytic functions CUME_DIST() FIRST_VALUE() LAST_VALUE() LEAD() LAG() PERCENTILE_CONT() PERCENTILE_DISC() PERCENT_RANK() - Cumulative Distribution - First value within the ordered partition - Last value within the ordered partition - Returns a following value based on an offset - Returns a prior value based on an offset - Percentile based on a continuous distribution - Percentile based on discreet column values - Relative rank of a row within a group of rows 19
  • 20.
    Other new Functions AggregateFunctions that can be used with the OVER Clause GROUPING() GROUPING_ID() - Replaces the COMPUTE clause - And gives us some new capabilities 20
  • 21.
    Demonstrations I will postthe examples to my SkyDrive and have a link on my Blog. I will be updating the examples as I come across useful applications. http://sdrv.ms/HZtKYP 21
  • 22.
    References Windows Functions inSQL https://www.simple-talk.com/sql/t-sql-programming/window-functions-in-sql/ Working with Window Functions in SQL Server https://www.simple-talk.com/sql/learn-sql-server/working-with-window-functions-in-sqlserver/ SQL Server 2012 Windowing Functions Part 1 of 2: Running and Sliding Aggregates http://lennilobel.wordpress.com/tag/t-sql-running-aggregates/ SQL Server Books Online – Over Clause http://technet.microsoft.com/en-us/library/ms189461.aspx 22
  • 23.

Editor's Notes

  • #2 Sample files will be posted shortly on my blog/skydrive
  • #6 Draw out a tree of the tables and their relationships, and what fields you need from each. Plan out any pre-aggregations needed that can be handled as CTE’s, limit results from joins etc.
  • #7 SQL Geek dilemma: Do I like Kirk or do I like Picard… Can’t recommend these guys books enough. Joe Celko’s SQL Puzzles in DBMS magazine were what really got my career in SQL development started.
  • #16 Allow for the creation of sliding windows across the rows in the frame, which enables all kinds of possibilities!
  • #17 RANGE uses a count of distinct values, where ROWS uses the count of the rows. Rows with the a “TIE” based on the Order By clause will be merged.Note that Azure Database (SQL Azure) does not fully support the SQL 2012 windowing functions yet.