You are on page 1of 28

Module 5: Working with Subqueries

Module 5: Working with Subqueries


Writing Basic Subqueries Writing Correlated Subqueries

Comparing Subqueries with Joins and Temporary Tables


Using Common Table Expressions

Lesson 1: Writing Basic Subqueries


What Are Subqueries? Using Subqueries as Expressions

Using the ANY, ALL, and SOME Operators


Scalar versus Tabular Subqueries Rules for Writing Subqueries

What Are Subqueries?


Queries nested inside a SELECT, INSERT, UPDATE, or DELETE statement Can be used anywhere an Expression is allowed

Example:
SELECT ProductID, Name FROM Production.Product WHERE Color NOT IN (SELECT Color FROM Production.Product WHERE ProductID = 5)

Result Set:
ProductID Name -------------------------------------1 Adjustable Race 2 Bearing Ball ... (504 row(s) affected)

Using Subqueries as Expressions


A Subquery can be substituted anywhere an expression can be used in the following statements, except in an ORDER BY list:

Example:

SELECT UPDATE

INSERT DELETE

SELECT Name, ListPrice, (SELECT AVG(ListPrice) FROM Production.Product) AS Average, ListPrice (SELECT AVG(ListPrice) FROM Production.Product) AS Difference FROM Production.Product WHERE ProductSubcategoryID = 1

Result Set:
Name ListPrice Average Difference --------------------------------------------------------Mountain-100 Silver, 38 3399.99 438.6662 2961.3238 Mountain-100 Silver, 42 3399.99 438.6662 2961.3238 ... (32 row(s) affected)

Using the ANY, ALL, and SOME Operators


Comparison operators that introduce a subquery can be modified by the keywords ALL or ANY

SOME is an ISO standard equivalent for ANY

ANY Example:
SELECT Name FROM Production.Product WHERE ListPrice >= ANY (SELECT MAX (ListPrice) FROM Production.Product GROUP BY ProductSubcategoryID)

Result Sets
Name --------------------LL Mountain Seat ML Mountain Seat ... (304 row(s) affected)

ALL Example:
SELECT Name FROM Production.Product WHERE ListPrice >= ALL (SELECT MAX (ListPrice) FROM Production.Product GROUP BY ProductSubcategoryID)

Name -------------------Road-150 Red, 62 Road-150 Red, 44... (5 row(s) affected)

Scalar versus Tabular Subqueries


A scalar subquery returns a single row of data, while a tabular subquery returns multiple rows of data

Scalar Subquery:
create table T1 (a int, b int) create table T2 (a int, b int) select * from T1 where T1.a > (select max(T2.a) from T2 where T2.b < T1.b)

Result Sets
a b ---------------------... (0 row(s) affected)

Tabular Subquery:
SELECT Name FROM Production.Product WHERE ListPrice = (SELECT ListPrice FROM Production.Product WHERE Name = 'Chainring Bolts' )

Name -----------------Adjustable Race Bearing Ball ... (200 row(s) affected)

Rules for Writing Subqueries


Subquery Allowances
Subqueries can be specified in many places A subquery can itself include one or more subqueries

Subquery Restrictions
SELECT list of a subquery introduced with a comparison operator can include only one expression WHERE clauses must be join-compatible ntext, text, and image data types cannot be used Column names in a statement are implicitly qualified by the table referenced in the FROM clause

Demonstration: Writing Basic Subqueries


In this demonstration, you will see how to:
Write a Basic Subquery

Use the ANY, ALL, and SOME Operators

Lesson 2: Writing Correlated Subqueries


What Are Correlated Subqueries? Building a Correlated Subquery

Using Correlated Subqueries


Using the EXISTS Clause with Correlated Subqueries

What Are Correlated Subqueries? 1


Outer query passes column values to the inner query

USE northwind SELECT orderid, customerid FROM orders AS or1 WHERE 20 < (SELECT quantity FROM [order details] AS od WHERE or1.orderid = od.orderid AND od.productid = 23) GO

Inner query uses that value to satisfy the inner query

Inner query returns a value back to the outer query

The process is repeated for the next row of the outer query

Back to Step 1

Building a Correlated Subquery


Outer Query
SELECT c.LastName, c.FirstName FROM Person.Person c JOIN HumanResources.Employee e ON e.BusinessEntityID = c.BusinessEntityID

Inner Query
SELECT Bonus FROM Sales.SalesPerson

Correlated Subquery
SELECT c.LastName, c.FirstName FROM Person.Person c JOIN HumanResources.Employee e ON e.BusinessEntityID = c.BusinessEntityID WHERE 5000.00 IN (SELECT Bonus FROM Sales.SalesPerson sp WHERE e.BusinessEntityID = sp.BusinessEntityID) ;

Using Correlated Subqueries


Correlated subqueries are executed repeatedly, once for each row that may be selected by the outer query

Example:
SELECT DISTINCT c.LastName, c.FirstName FROM Person.Person c JOIN HumanResources.Employee e ON e.BusinessEntityID = c.BusinessEntityID WHERE 5000.00 IN (SELECT Bonus FROM Sales.SalesPerson sp WHERE e.BusinessEntityID = sp.BusinessEntityID);

Result Set:
LastName FirstName ----------------------------Ansman-Wolfe Pamela Saraive Jos (2 row(s) affected)

Using the EXISTS Clause with Correlated Subqueries


When a subquery is introduced with the keyword EXISTS, the subquery functions as an existence test

Example:
SELECT Name FROM Production.Product WHERE EXISTS (SELECT * FROM Production.ProductSubcategory WHERE ProductSubcategoryID = Production.Product.ProductSubcategoryID AND Name = 'Wheels')

Result Set:
Name -----------------------LL Mountain Front Wheel ML Mountain Front Wheel ... (14 row(s) affected)

Demonstration: Writing Correlated Subqueries


In this demonstration, you will see how to:
Write a Correlated Subquery

Create a Correlated Subquery with Comparison Operators

Lesson 3: Comparing Subqueries with Joins and Temporary Tables


Subqueries versus Joins Temporary Tables

Subqueries versus Temporary Tables

Subqueries versus Joins


Joins can yield better performance in some cases where existence must be checked Joins are performed faster by SQL Server than subqueries Subqueries can often be rewritten as joins SQL Server 2008 query optimizer is intelligent enough to covert a subquery into a join if it can be done Subqueries are useful for answering questions that are too complex to answer with joins

Temporary Tables
Local Temporary Tables:
Have a single number sign (#) as the first character of their names Visible only to the current connection for the user Deleted when the user disconnects from SQL Server CREATE TABLE #StoreInfo ( EmployeeID int, ManagerID int, Num int )

Global Temporary Tables:


Have a double number sign (##) as the first character of their names Visible to any user once created Deleted when all users referencing them disconnect

CREATE TABLE ##StoreInfo ( EmployeeID int, ManagerID int, Num int )

Subqueries versus Temporary Tables

As subqueries get more complex their performance may decrease Maintainability can be easier with subqueries in some situations, and easier with temporary tables in others

Temporary tables can be easier for some to debug while others prefer to work with a single subquery

Lesson 4: Using Common Table Expressions


What Are Common Table Expressions? Writing Common Table Expressions

Writing Recursive Queries by Using Common Table

Expressions

What Are Common Table Expressions?


Common Table Expression
or DELETE

A named temporary result set based on a SELECT query

Result set can be used in SELECT, INSERT, UPDATE, Advantages of common table expressions:

Queries with derived tables become more readable Provide traversal of recursive hierarchies

WITH TopSales (SalesPersonID, NumSales) AS ( SELECT SalesPersonID, Count(*) FROM Sales.SalesOrderHeader GROUP BY SalesPersonId ) SELECT * FROM TopSales WHERE SalesPersonID IS NOT NULL ORDER BY NumSales DESC

Writing Common Table Expressions 1


Choose a CTE name and column list
Create the CTE SELECT query Use the CTE in a query

2
3

WITH TopSales (SalesPersonID, NumSales) AS (SELECT SalesPersonID, Count(*) FROM Sales.SalesOrderHeader GROUP BY SalesPersonId) SELECT LoginID, NumSales FROM HumanResources.Employee e INNER JOIN TopSales ON TopSales.SalesPersonID = e.EmployeeID ORDER BY NumSales DESC

Writing Recursive Queries by Using Common Table Expressions


Modify CTE SELECT query when creating CTE:

1 2 3

Create the anchor member query (top of recursion tree) Add the UNION ALL operator Create the recursive member query that self-references the CTE

SELECT ManagerID, EmployeeID FROM HumanResources.Employee WHERE ManagerID IS NULL


UNION ALL SELECT e.ManagerID, e.EmployeeID FROM HumanResources.Employee e INNER JOIN HumanResources.Employee mgr ON e.ManagerID = mgr.EmployeeID

Demonstration: Using Common Table Expressions


In this demonstration, you will see how to:
Write a Common Table Expression

Write a Recursive Query

Lab: Working with Subqueries


Exercise 1: Writing Basic Subqueries Exercise 2: Writing Correlated Subqueries

Exercise 3: Comparing Subqueries with Joins and

Temporary Tables

Exercise 4: Using Common Table Expressions

Logon information

Virtual machine User name Password

NY-SQL-01 Administrator Pa$$w0rd

Estimated time: 60 minutes

Lab Scenario
You are a database developer at Adventure Works. You have

been asked by several managers of the company to prepare a number of reports in order to help the executive committee determine the budget for next year.

Lab Review
How are basic subqueries evaluated? How are correlated subqueries evaluated?

What could a Common Table Expression be used for?

Module Review and Takeaways


Review Questions Best Practices

You might also like