Problems displaying this newsletter? View online.
Database Weekly
The Complete Weekly Roundup of SQL Server News
Hand-picked content to sharpen your professional edge
Editorial
 

Common Table Expression Misunderstandings

I frequently use Common Table Expressions (CTEs) when I demo windowing functions and get questions about them. Windowing functions are limited to the SELECT and OVER clause which means that you can’t filter or group on them directly. Using a CTE is one way to separate the logic of the query into multiple steps so that you filter or group after the windowing function executes. Another reason might be nesting aggregate functions, such as needing the average of the sums. Again, you can’t do that directly and using a CTE is one way to solve it.

I was once given a query containing nested subqueries (aka derived tables) a dozen layers deep. The team wanted me to verify that the query did what it was supposed to do, which was very difficult. I ended up translating the query into CTEs where one CTE queried the previous CTE instead of nesting. I also added comments at each level to explain what was going on. The team was thrilled that they could now make sense of the query.

Are CTEs my ultimate T-SQL tool? Not at all. I do love how CTEs are organized and will often start with them. However, if there is a performance issue, I’ll try something else.

I’ve run into a few people who would never use a CTE because they think they always cause performance issues. I’ve also talked to some others who believe they have some functionality that doesn’t exist. Surprisingly, these two are related.

One big difference between a derived table and a CTE is that a derived table cannot be used multiple times in the query while a CTE can. You could define a CTE that joins to itself in the outer query, for example. A derived table must be defined for each time it’s used. Here’s where the misunderstandings begin.

When a CTE is used more than once in a query, SQL Server executes that CTE the same number of times and possibly with different indexes and operators depending on how it's used each time. The results of the CTE are not cached in memory for reuse.

Here’s a simple non-CTE example from AdventureWorks:

SET STATISTICS IO ON;
GO
SELECT CustomerID
FROM Sales.Customer
UNION ALL
SELECT CustomerID
FROM Sales.Customer;

It’s obvious that this will touch the Sales.Customer table twice. The query uses 74 logical reads and scans the table twice.

Here’s another example where a CTE is used. Sales.Customer is in the query just once, and UNION ALL is used in the outer query.

WITH Customers AS (
  SELECT CustomerID
  FROM Sales.Customer)
SELECT *
FROM Customers
UNION ALL
SELECT * FROM Customers;

Some people think that the second query will only touch the Sales.Customer table once and cache the results, but it’s actually identical to the previous query. It also uses 74 logical reads and scans the table twice, and the execution plans are identical.

There’s no difference in the two examples. SQL Server doesn’t save the results of the CTE for multiple uses in the outer query. I’m hopeful that they do work like this in some future version of SQL Server. When the CTE is used many times in the outer query, performance might deteriorate when you don’t expect it. This doesn’t mean that you should never use a CTE; it means that you need to understand how they work.

Another misconception I’ve run into lately involves the scope of the CTE. It lives only within one statement. You can’t define a CTE and then use it in multiple queries like a temp table.

I hope this has cleared up some of the misconceptions about CTEs and that they remain a useful tool in your T-SQL toolbox.

 

Kathi Kellenberger

Join the debate, and respond to the editorial on the forums

 
The Weekly News
All the headlines and interesting SQL Server information that we've collected over the past week, and sometimes even a few repeats if we think they fit.
Vendors/3rd Party Products

Getting Data In and Out of SQL Server Flyway Builds

Phil Factor provides SQL routines to extract data from and load data into a SQL Server database, using BCP, and then a PowerShell automation script that uses Flyway to automatically build a database, from scratch and then fill it with data, ready for testing.

Administration of SQL Server

Storage 101: RAID

RAID has been around since the 90s to ensure perfo...

Different Ways to Rename SQL Server Tables

One of the most critical databa...

Documentation for dm_db_missing_index_group_stats_query

No, It’s New When I was checking out early build...

Automatic Sample Sizes for Statistics Updates

Looking at how SQL Server samples your data when doing auto-stats updates. Part of a series on understanding statistics, to help you achieve optimal performance of your queries on... The...

Azure SQL Database

Deploying Azure SQL Database Bacpac and Terraform

This post will take a look at how to deploy a bacpac to Azure SQL Database...

Computing in the Cloud (Azure, Google, AWS)

Upgrading Durable Function Extension of my Azure Function App

With more applications and services being placed into a vendor cloud environment, it does require almost no effort to manage and maintain the infrastructure these applications and services are running on...

DMO/SMO/Powershell

How to import/export data between SQL Server and Excel using PowerShell?

ImportExcel is a powerful tool to manage MS Excel,...

Data Science

How to become a data scientist: A data-driven approach to careers in data science

Many devs and IT professionals looking for the next career wonder how to become a data scientist. Ashwin Thota matches up skills to job titles.

ETL/SSIS/Azure Data Factory/Biml

Building Custom Tasks for SQL Server Integration Services, 2nd Edition is Available

I am honored, humbled, and excited to announce the...

Performance Tuning SQL Server

Plansplaining, part 16. Temporal tables (part 1)

Welcome to part sixteen of the plansplaining series...

SARGable Isn’t Just For Your Where Clause

Maybe Probably It’s likely also obvious that your join clauses should also be SARGable. Doing something like this is surely just covering up for some daft data quality issues....

SQL Server 2019 Intelligent Query Processing: Memory Grant Feedback

In our previous posts of Memory Grant Internals, we have learned all about the memory grant internals...

Do You Really Need that Order By?

I recently came across a scenario where an application process was not performing correctly on one database but was working fine on others...

Identifying SQL Server Performance Problems Part 3

Continuing with our Performance Tuning series as you have learned baselining and knowing your normal system performance metrics is an important part of performance tuning. In part 1 we...

PowerPivot/PowerQuery/PowerBI

Power BI Quick Tip: the Formula Bar in Power Query

Often you do the transformation in Power Query usi...

Query Folding On SQL Queries In Power Query Using Value.NativeQuery() and EnableFolding=true

Here’s something that will Blow Your Mind if you...

What is Power BI and Why Should I Care?

As my regular readers may know, I am the co-organi...

Power BI Drill Through using Multiple Data Points

A drill through in Power BI allows the reader to see secondary data related to the original page with the context of a specific data point applied, for example,...

Power Query – Continuous Week on Week Comparison

Below is the Power Query syntax to allow for Week-...

Why Power BI loves a Star Schema

Are you using a flat table in your Power BI report...

Professional Development

Welcome to the Azure Data Community, empowered by Microsoft

After the Professional Association of SQL Server (...

Creating presentations with Reveal and Github pages

I really don’t like Powerpoint. I’ll do pretty...

SQL Server Security and Auditing

SQL Server authentication methods, logins, and database users

Understanding SQL Server security is a critical sk...

T-SQL

How to Write Simple SQL Queries from a Blank Database

This article explains writing simple SQL queries from the most basic ones and gradually improving the script to solve some mathematical and date-related problems...

SQL REPLACE: The Top 5 Facts to Find and Replace SQL Texts

Total: 2 Average: 5 Today’s code editors and word processors come with a search and replace feature. It is helpful when you need to change a word or a...

CTE Book Sample Code

As part of the CTE book there is a sample database...

Old but not gone…

I am part of a weekly talk show we run at the TriP...

Hierarchical Queries

The following is chapter 5 from my Common Table E...

 
RSS FeedTwitter
This email has been sent to {email}. To be removed from this list, please click here. If you have any problems leaving the list, please contact the webmaster@sqlservercentral.com. This newsletter was sent to you because you signed up at SQLServerCentral.com. Note: This is not the SQLServerCentral.com daily newsletter list, and unsubscribing to this newsletter will not stop you receiving the SQL Server Central daily newsletters. If you want to be removed from that list, you can follow the instructions on the daily newsletter.
©2019 Redgate Software Ltd, Newnham House, Cambridge Business Park, Cambridge, CB4 0WZ, United Kingdom. All rights reserved.
webmaster@sqlservercentral.com

 

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -