The SELECT reserved word is part of the Data Manipulation Language (DML) defined by Codd and is used to query data from the database. Because of its popularity, there are many clauses and functions that can be used to construct a query to retrieve data.
Today, I am continuing our exploration of this reserved word by reviewing queries that merge data using the APPLY operator. The APPLY operator come in two flavors: CROSS and OUTER. I am going to concentrate on the later during this discussion.
I will be using the Adventure Works 2012 sample database supplied by Microsoft during this talk.
1 2 3 4 5 |
<span style="color: #008000;">-- Use Adventure Works USE [AdventureWorks2012] GO </span> |
Let us start our exploration off by getting the business requirements for the query from the Sales & Marketing manager. (S)he wants to see if item color influences a customers choice of the product. I will be using the multiline table value function, [ufnColor2RgbValues], that I created in a previous blog.
Since both the CROSS and OUTER APPLY operators are very similar in nature, I want to compare and contrast their properties.
Think of the CROSS APPLY operator as a INNER JOIN with a correlated sub-query. The TSQL code below returns 30 rows. However, 14 rows were dropped from the result set due to them not having a color defined.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<span style="color: #008000;">-- Cross Apply same as inner join, drops 14 records - (30 rows) SELECT PC1.Name as MainCategory , PS1.Name as SubCategory , RGB.Name as ItemColor , RGB.HexCode as HexCode , SUM(Quantity) as SumItemStock , AVG(P1.ListPrice) as AvgItemList , AVG(P1.StandardCost) as AvgItemCost FROM [Production].[ProductInventory] AS PI1 LEFT JOIN [Production].[Product] AS P1 ON PI1.ProductID = P1.ProductID LEFT JOIN [Production].[ProductSubcategory] AS PS1 ON P1.ProductSubcategoryID = PS1.ProductSubcategoryID LEFT JOIN [Production].[ProductCategory] as PC1 ON PS1.ProductCategoryID = PC1.ProductCategoryID CROSS APPLY [dbo].[ufnColor2RgbValues] (P1.Color) AS RGB WHERE PC1.Name IS NOT NULL GROUP BY PC1.Name , PS1.Name , RGB.Name , RGB.HexCode GO </span> |
On the other hand, think of the OUTER APPLY operator as a LEFT JOIN with a correlated sub-query. Because of this property, all 44 rows of data are returned in the result set.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<span style="color: #008000;">-- Out Apply same as left outer join - (44 rows) SELECT PC1.Name as MainCategory , PS1.Name as SubCategory , RGB.Name as ItemColor , RGB.HexCode as HexCode , SUM(Quantity) as SumItemStock , AVG(P1.ListPrice) as AvgItemList , AVG(P1.StandardCost) as AvgItemCost FROM [Production].[ProductInventory] AS PI1 LEFT JOIN [Production].[Product] AS P1 ON PI1.ProductID = P1.ProductID LEFT JOIN [Production].[ProductSubcategory] AS PS1 ON P1.ProductSubcategoryID = PS1.ProductSubcategoryID LEFT JOIN [Production].[ProductCategory] as PC1 ON PS1.ProductCategoryID = PC1.ProductCategoryID OUTER APPLY [dbo].[ufnColor2RgbValues] (P1.Color) AS RGB WHERE PC1.Name IS NOT NULL GROUP BY PC1.Name , PS1.Name , RGB.Name , RGB.HexCode GO </span> |
In a nutshell, the CROSS APPLY and OUTER APPLY operators are like two fraternal twins. Both have the common characteristic of joining data to a sub-query or table valued function. Nonetheless, they do not merge data the same way. This characteristic makes them not identical. One operator does a INNER JOIN and the other does a LEFT JOIN.
If you have a correlated sub query in the future, think about using these constructs. Check out Rob Farley’s article and his thoughts on the subject.
Next time I will be talking about the GROUP SETS which is part of my Summarizing Data Series.