Using Subqueries as Expressions Using the ANY, ALL, and SOME Operators Comparison operators that introduce A Subquery can be modified by the keywords ANY or ANY.
Using Subqueries as Expressions Using the ANY, ALL, and SOME Operators Comparison operators that introduce A Subquery can be modified by the keywords ANY or ANY.
Using Subqueries as Expressions Using the ANY, ALL, and SOME Operators Comparison operators that introduce A Subquery can be modified by the keywords ANY or ANY.
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
SELECT ProductID, Name FROM Production.Product WHERE Color NOT IN (SELECT Color FROM Production.Product WHERE ProductID = 5) ProductID Name -------------------------------------- 1 Adjustable Race 2 Bearing Ball ... (504 row(s) affected) Result Set: Example: Using Subqueries as Expressions 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 A Subquery can be substituted anywhere an expression can be used in the following statements, except in an ORDER BY list: SELECT
UPDATE
INSERT
DELETE
Example: 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) Result Set: Using the ANY, ALL, and SOME Operators Comparison operators that introduce a subquery can be modified by the keywords ALL or ANY SELECT Name FROM Production.Product WHERE ListPrice >= ANY (SELECT MAX (ListPrice) FROM Production.Product GROUP BY ProductSubcategoryID) SOME is an ISO standard equivalent for ANY SELECT Name FROM Production.Product WHERE ListPrice >= ALL (SELECT MAX (ListPrice) FROM Production.Product GROUP BY ProductSubcategoryID) Name --------------------- LL Mountain Seat ML Mountain Seat ... (304 row(s) affected) Name -------------------- Road-150 Red, 62 Road-150 Red, 44... (5 row(s) affected) ANY Example: ALL Example: Result Sets Scalar versus Tabular Subqueries 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) A scalar subquery returns a single row of data, while a tabular subquery returns multiple rows of data SELECT Name FROM Production.Product WHERE ListPrice = (SELECT ListPrice FROM Production.Product WHERE Name = 'Chainring Bolts' ) a b ---------------------- ... (0 row(s) affected) Name ------------------ Adjustable Race Bearing Ball ... (200 row(s) affected) Scalar Subquery: Tabular Subquery: Result Sets
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? 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 1 Inner query uses that value to satisfy the inner query 2 Inner query returns a value back to the outer query 3 The process is repeated for the next row of the outer query 4 Back to Step 1 Building a 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) ; SELECT Bonus FROM Sales.SalesPerson SELECT c.LastName, c.FirstName FROM Person.Person c JOIN HumanResources.Employee e ON e.BusinessEntityID = c.BusinessEntityID Inner Query Outer Query Correlated Subquery + Using Correlated Subqueries 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); Example: LastName FirstName ----------------------------- Ansman-Wolfe Pamela Saraive Jos (2 row(s) affected) Result Set: Correlated subqueries are executed repeatedly, once for each row that may be selected by the outer query Using the EXISTS Clause with Correlated Subqueries SELECT Name FROM Production.Product WHERE EXISTS (SELECT * FROM Production.ProductSubcategory WHERE ProductSubcategoryID = Production.Product.ProductSubcategoryID AND Name = 'Wheels') When a subquery is introduced with the keyword EXISTS, the subquery functions as an existence test Name ------------------------ LL Mountain Front Wheel ML Mountain Front Wheel ... (14 row(s) affected) Result Set: Example: 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 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 ) 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? Result set can be used in SELECT, INSERT, UPDATE, or DELETE 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 A named temporary result set based on a SELECT query Common Table Expression Writing Common Table Expressions Choose a CTE name and column list 1 WITH TopSales (SalesPersonID, NumSales) AS WITH TopSales (SalesPersonID, NumSales) AS (SELECT SalesPersonID, Count(*) FROM Sales.SalesOrderHeader GROUP BY SalesPersonId) Create the CTE SELECT query 2 Use the CTE in a query 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
WITH TopSales (SalesPersonID, NumSales) AS ( SELECT SalesPersonID, Count(*) FROM Sales.SalesOrderHeader GROUP BY SalesPersonId )
Ejecucin
SELECT * FROM TopSales WHERE SalesPersonID IS NOT NULL ORDER BY NumSales DESC Writing Recursive Queries by Using Common Table Expressions Modify CTE SELECT query when creating CTE: Create the anchor member query (top of recursion tree) 1 SELECT ManagerID, EmployeeID FROM HumanResources.Employee WHERE ManagerID IS NULL
Add the UNION ALL operator 2 SELECT ManagerID, EmployeeID FROM HumanResources.Employee WHERE ManagerID IS NULL
UNION ALL Create the recursive member query that self-references the CTE 3 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 NY-SQL-01 User name Administrator Password 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