Use Built
Use Built
In this lab, you'll use built-in functions to retrieve and aggregate data in
the adventureworks database. For your reference, the following diagram shows the
tables in the database (you may need to resize the pane to see them clearly).
Note: If you're familiar with the standard AdventureWorks sample database, you may
notice that in this lab we are using a simplified version that makes it easier to focus on
learning Transact-SQL syntax.
Scalar functions
Transact-SQL provides a large number of functions that you can use to extract
additional information from your data. Most of these functions are scalar functions that
return a single value based on one or more input parameters, often a data field.
Tip: We don't have enough time in this exercise to explore every function available in
Transact-SQL. To learn more about the functions covered in this exercise, and more,
view the Transact-SQL documentation.
1. Start Azure Data Studio, and create a new query (you can do this from
the File menu or on the welcome page).
2. In the new SQLQuery_… pane, use the Connect button to connect the query to
the AdventureWorks saved connection.
3. In the query editor, enter the following code.
4. SELECT YEAR(SellStartDate) AS SellStartYear, ProductID, Name
5. FROM SalesLT.Product
ORDER BY SellStartYear;
6. Use the ⏵Run button to run the query, and and after a few seconds, review the
results, noting that the YEAR function has retrieved the year from
the SellStartDate field.
7. Modify the query as follows to use some additional scalar functions that operate
on datetime values.
8. SELECT YEAR(SellStartDate) AS SellStartYear,
9. DATENAME(mm,SellStartDate) AS SellStartMonth,
10. DAY(SellStartDate) AS SellStartDay,
11. DATENAME(dw, SellStartDate) AS SellStartWeekday,
12. DATEDIFF(yy,SellStartDate, GETDATE()) AS YearsSold,
13. ProductID,
14. Name
15. FROM SalesLT.Product
ORDER BY SellStartYear;
Note also that the DATEDIFF function returns the specified time interval
between and start date and an end date. In this case the interval is measured in
years (yy), and the end date is determined by the GETDATE function; which
when used with no parameters returns the current date and time.
19. Run the query and note that it returns the concatenated first and last name for
each customer.
20. Replace the query with the following code to explore some more functions that
manipulate string-based values.
21. SELECT UPPER(Name) AS ProductName,
22. ProductNumber,
23. ROUND(Weight, 0) AS ApproxWeight,
24. LEFT(ProductNumber, 2) AS ProductType,
25. SUBSTRING(ProductNumber,CHARINDEX('-', ProductNumber) + 1,
4) AS ModelCode,
26. SUBSTRING(ProductNumber, LEN(ProductNumber) - CHARINDEX('-',
REVERSE(RIGHT(ProductNumber, 3))) + 2, 2) AS SizeCode
FROM SalesLT.Product;
27. Run the query and note that it returns the following data:
o The product name, converted to upper case by the UPPER function.
o The product number, which is a string code that encapsulates details of
the product.
o The weight of the product, rounded to the nearest whole number by using
the ROUND function.
o The product type, which is indicated by the first two characters of the
product number, starting from the left (using the LEFT function).
o The model code, which is extracted from the product number by using
the SUBSTRING function, which extracts the four characters
immediately following the first - character, which is found using
the CHARINDEX function.
o The size code, which is extracted using the SUBSTRING function to
extract the two characters following the last - in the product code. The
last - character is found by taking the total length (LEN) of the product
ID and finding its index (CHARINDEX) in the reversed (REVERSE)
first three characters from the right (RIGHT). This example shows how
you can combine functions to apply fairly complex logic to extract the
values you need.
4. Run the query and note that the results only products with a numeric size.
5. Replace the query with the following code, which nests
the ISNUMERIC function used previously in an IIF function; which in turn
evaluates the result of the ISNUMERIC function and returns Numeric if the
result is 1 (true), and Non-Numeric otherwise.
6. SELECT Name, IIF(ISNUMERIC(Size) = 1, 'Numeric', 'Non-Numeric') AS
SizeType
FROM SalesLT.Product;
14. Run the query and note that the CHOOSE function returns the value in the
ordinal position in a list based on the a specified index value. The list index is 1-
based so in this query the function returns Bikes for category 1, Components for
category 2, and so on.
5. Run the query and note that the following aggregations are returned:
o The number of products in the table. This is returned by using
the COUNT function to count the number of rows (*).
o The number of categories. This is returned by using
rhe COUNT function to count the number of distinct category IDs in the
table.
o The average price of a product. This is returned by using
the AVG function with the ListPrice field.
6. Replace the query with the following code.
7. SELECT COUNT(p.ProductID) AS BikeModels, AVG(p.ListPrice) AS
AveragePrice
8. FROM SalesLT.Product AS p
9. JOIN SalesLT.ProductCategory AS c
10. ON p.ProductCategoryID = c.ProductCategoryID
WHERE c.Name LIKE '%Bikes';
11. Run the query, noting that it returns the number of models and the average price
for products with category names that end in "bikes".
5. Run the query and note that it returns the number of customers assigned to each
salesperson.
6. Replace the query with the following code:
7. SELECT c.Salesperson, SUM(oh.SubTotal) AS SalesRevenue
8. FROM SalesLT.Customer c
9. JOIN SalesLT.SalesOrderHeader oh
10. ON c.CustomerID = oh.CustomerID
11. GROUP BY c.Salesperson
ORDER BY SalesRevenue DESC;
12. Run the query, noting that it returns the total sales revenue for each salesperson
who has completed any sales.
13. Modify the query as follows to use an outer join:
14. SELECT c.Salesperson, ISNULL(SUM(oh.SubTotal), 0.00) AS
SalesRevenue
15. FROM SalesLT.Customer c
16. LEFT JOIN SalesLT.SalesOrderHeader oh
17. ON c.CustomerID = oh.CustomerID
18. GROUP BY c.Salesperson
ORDER BY SalesRevenue DESC;
19. Run the query, noting that it returns the sales totals for salespeople who have
sold items, and 0.00 for those who haven't.
1. Replace the existing query with the following code, which you may think would
return salespeople with more than 100 customers (but you'd be wrong, as you
will see!)
2. SELECT Salesperson, COUNT(CustomerID) AS Customers
3. FROM SalesLT.Customer
4. WHERE COUNT(CustomerID) > 100
5. GROUP BY Salesperson
ORDER BY Salesperson;
6. Run the query and note that it returns an error. The WHERE clause is
applied before the aggregations and the GROUP BY clause, so you can't use it
to filter on the aggregated value.
7. Modify the query as follows to add a HAVING clause, which is
applied after the aggregations and GROUP BY clause.
8. SELECT Salesperson, COUNT(CustomerID) AS Customers
9. FROM SalesLT.Customer
10. GROUP BY Salesperson
11. HAVING COUNT(CustomerID) > 100
ORDER BY Salesperson;
12. Run the query, and note that it returns only salespeople who have more than 100
customers assigned to them.
Challenges
Now it's time to try using functions to retrieve data in some queries of your own.
Tip: Try to determine the appropriate queries for yourself. If you get stuck, suggested
answers are provided at the end of this lab.
Challenge 1: Retrieve order shipping information
The operations manager wants reports about order shipping based on data in
the SalesLT.SalesOrderHeader table.
The sales manager would like reports that include aggregated information about product
sales.
Challenge Solutions
This section contains suggested solutions for the challenge queries.
Challenge 1
Challenge 2
The product manager would like reports that include aggregated information about
product sales.
7. Filter the product sales list to include only products that cost over 1,000:
8. SELECT p.Name,SUM(o.LineTotal) AS TotalRevenue
9. FROM SalesLT.SalesOrderDetail AS o
10. JOIN SalesLT.Product AS p
11. ON o.ProductID = p.ProductID
12. WHERE p.ListPrice > 1000
13. GROUP BY p.Name
ORDER BY TotalRevenue DESC;
14. Filter the product sales groups to include only total sales over 20,000:
15. SELECT p.Name,SUM(o.LineTotal) AS TotalRevenue
16. FROM SalesLT.SalesOrderDetail AS o
17. JOIN SalesLT.Product AS p
18. ON o.ProductID = p.ProductID
19. WHERE p.ListPrice > 1000
20. GROUP BY p.Name
21. HAVING SUM(o.LineTotal) > 20000
ORDER BY TotalRevenue DESC;
1. When you've finished the exercise, complete the knowledge check in Microsoft
Learn.
2. When the link above opens in another browser tab, return to this one to end the lab
environment.