Advanced SELECTs

In this lesson of the SQL tutorial, you will learn...
  1. To use SELECT statements to retrieve calculated values.
  2. To work with aggregate functions and grouping.
  3. To work with SQL's data manipulation functions.

Calculated Fields

Calculated fields are fields that do not exist in a table, but are created in the SELECT statement. For example, you might want to create FullName from FirstName and LastName.

Concatenation

Concatenation is a fancy word for stringing together different words or characters. SQL Server, Oracle and MySQL each has its own way of handling concatenation. All three of the code samples below will return the following results:

In SQL Server, the plus sign (+) is used as the concatenation operator.

Code Sample: AdvancedSelects/Demos/Concatenate-SqlServer.sql

-- Select the full name of all employees. SQL SERVER.

SELECT FirstName + ' ' + LastName
FROM Employees;

In Oracle, the double pipe (||) is used as the concatenation operator.

Code Sample: AdvancedSelects/Demos/Concatenate-Oracle.sql

-- Select the full name of all employees. Oracle.

SELECT FirstName || ' ' || LastName
FROM Employees;

MySQL does this in yet another way. There is no concatenation operator. Instead, MySQL uses the CONCAT() function .

Code Sample: AdvancedSelects/Demos/Concatenate-MySQL.sql

-- Select the full name of all employees. MySQL.
SELECT CONCAT(FirstName, ' ', LastName)
FROM Employees;

Note that concatenation only works with strings. To concatenate other data types, you must first convert them to strings.

Mathematical Calculations

Mathematical calculations in SQL are similar to those in other languages.

Mathematical Operators
Operator Description
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulus

Code Sample: AdvancedSelects/Demos/MathCalc.sql

/*
If the cost of freight is greater than or equal to $500.00,
it will now be taxed by 10%. Create a report that shows the
order id, freight cost, freight cost with this tax for all
orders of $500 or more.
*/

SELECT OrderID, Freight, Freight * 1.1
FROM Orders
WHERE Freight >= 500;
Code Explanation

The above SELECT statement will return the following results:

Aliases

You will notice in the examples above that the calculated columns have the header "(No column name)". The keyword AS is used to provide a named header for the column.

Code Sample: AdvancedSelects/Demos/Alias.sql

SELECT OrderID, Freight, Freight * 1.1 AS FreightTotal
FROM Orders
WHERE Freight >= 500;
Code Explanation

As you can see, the third column now has the title "FreightTotal".

Aggregate Functions and Grouping

Aggregate Functions

Aggregate functions are used to calculate results using field values from multiple records. There are five common aggregate functions.

Common Aggregate Functions
Aggregate Function Description
COUNT() Returns the number of rows containing non-NULL values in the specified field.
SUM() Returns the sum of the non-NULL values in the specified field.
AVG() Returns the average of the non-NULL values in the specified field.
MAX() Returns the maximum of the non-NULL values in the specified field.
MIN() Returns the minimum of the non-NULL values in the specified field.

Code Sample: AdvancedSelects/Demos/Aggregate-Count.sql

-- Find the Number of Employees

SELECT COUNT(*) AS NumEmployees
FROM Employees;
Code Explanation

Returns 9.

Code Sample: AdvancedSelects/Demos/Aggregate-Sum.sql

-- Find the Total Number of Units Ordered of Product ID 3

/******************************
SQL Server
******************************/
SELECT SUM(Quantity) AS TotalUnits
FROM "Order Details"
WHERE ProductID=3;

/******************************
Oracle and MySQL
******************************/
SELECT SUM(Quantity) AS TotalUnits
FROM Order_Details
WHERE ProductID=3;
Code Explanation

Returns 328.

Code Sample: AdvancedSelects/Demos/Aggregate-Avg.sql

-- Find the Average Unit Price of Products

SELECT AVG(UnitPrice) AS AveragePrice
FROM Products;
Code Explanation

Returns 28.8663.

Code Sample: AdvancedSelects/Demos/Aggregate-MinMax.sql

-- Find the Earliest and Latest Dates of Hire

SELECT MIN(HireDate) AS FirstHireDate,
 MAX(HireDate) AS LastHireDate
FROM Employees;
Code Explanation

The above SELECT statement will return April 1, 1992 and November 15, 1994 as the FirstHireDate and LastHireDate, respectively. The date format will vary from database to database.

Grouping Data

GROUP BY

With the GROUP BY clause, aggregate functions can be applied to groups of records based on column values. For example, the following code will return the number of employees in each city.

Code Sample: AdvancedSelects/Demos/Aggregate-GroupBy.sql

--Retrieve the number of employees in each city

SELECT City, COUNT(EmployeeID) AS NumEmployees
FROM Employees
GROUP BY City;

The above SELECT statement will return the following results:

HAVING

The HAVING clause is used to filter grouped data. For example, the following code specifies that we only want information on cities that have more than one employee.

Code Sample: AdvancedSelects/Demos/Aggregate-Having.sql

/*
 Retrieve the number of employees in each city 
 in which there are at least 2 employees.
*/

SELECT City, COUNT(EmployeeID) AS NumEmployees
FROM Employees
GROUP BY City
HAVING COUNT(EmployeeID) > 1;

The above SELECT statement will return the following results:

Order of Clauses

  1. SELECT
  2. FROM
  3. WHERE
  4. GROUP BY
  5. HAVING
  6. ORDER BY

Code Sample: AdvancedSelects/Demos/Aggregate-OrderOfClauses.sql

/*
 Find the number of sales representatives in each city that contains 
 at least 2 sales representatives. Order by the number of employees.
*/

SELECT City, COUNT(EmployeeID) AS NumEmployees
FROM Employees
WHERE Title = 'Sales Representative'
GROUP BY City
HAVING COUNT(EmployeeID) > 1
ORDER BY NumEmployees;

The above SELECT statement will return the following results:

Grouping Rules

  • Every non-aggregate column that appears in the SELECT clause must also appear in the GROUP BY clause.
  • You may not use aliases in the HAVING clause.
  • You may use aliases in the ORDER BY clause.
  • You may only use calculated fields in the HAVING clause.
  • You may use calculated field aliases or actual fields in the ORDER BY clause.

Selecting Distinct Records

The DISTINCT keyword is used to select distinct combinations of column values from a table. For example, the following example shows how you would find all the distinct cities in which Northwind has employees.

Code Sample: AdvancedSelects/Demos/Distinct.sql

/*
Find all the distinct cities in which Northwind has employees.
*/

SELECT DISTINCT City
FROM Employees
ORDER BY City

DISTINCT is often used with aggregate functions. The following example shows how DISTINCT can be used to find out in how many different cities Northwind has employees.

Code Sample: AdvancedSelects/Demos/Distinct-Count.sql

/*
Find out in how many different cities Northwind has employees.
*/

SELECT COUNT(DISTINCT City) AS NumCities
FROM Employees

Built-in Data Manipulation Functions

In this section, we will discuss some of the more common built-in data manipulation functions. Unfortunately, the functions differ greatly between databases, so you should be sure to check your database documentation when using these functions.

The tables below show some of the more common math, string, and date functions.

Common Math Functions

Common Math Functions
Description SQL Server Oracle MySQL
Absolute value ABS ABS ABS
Smallest integer >= value CEILING CEIL CEILING
Round down to nearest integer FLOOR FLOOR FLOOR
Power POWER POWER POWER
Round ROUND ROUND ROUND
Square root SQRT SQRT SQRT
Formatting numbers to two decimal places CAST(num AS decimal(8,2)) TO_CHAR(num,'9.00') FORMAT(num,2)

Code Sample: AdvancedSelects/Demos/Functions-Math1.sql

/*
Select freight as is and
freight rounded to the first decimal (e.g, 1.150 becomes 1.200)
from the Orders tables
*/

SELECT Freight, ROUND(Freight,1)  AS ApproxFreight
FROM Orders;
Code Explanation

The above SELECT statement will return the following results (not all rows shown):

Code Sample: AdvancedSelects/Demos/Functions-Math2.sql

/*
Select the unit price as is and
unit price as a decimal with 2 places to the right of the decimal point
from the Products tables
*/
/******************************
SQL Server and MySQL
******************************/
SELECT UnitPrice, CAST(UnitPrice AS Decimal(8,2))
FROM Products;

/******************************
Oracle
******************************/
SELECT UnitPrice, TO_CHAR(UnitPrice,'999.99')
FROM Products;
Code Explanation

The above SELECT statement will return the following results (not all rows shown):

Note that you would round to a whole number by passing 0 as the second parameter: ROUND(field,0); and to the tens place by passing -1: ROUND(field,-1).

Common String Functions

Common String Functions
Description SQL Server Oracle MySQL
Convert characters to lowercase LOWER LOWER LOWER
Convert characters to uppercase UPPER UPPER UPPER
Remove trailing blank spaces RTRIM RTRIM RTRIM
Remove leading blank spaces LTRIM LTRIM LTRIM
Substring SUBSTRING SUBSTR SUBSTRING

Code Sample: AdvancedSelects/Demos/Functions-String1.sql

/*
Select first and last name from employees in all uppercase letters
*/
SELECT UPPER(FirstName), UPPER(LastName)
FROM Employees;
Code Explanation

The above SELECT statement will return the following results:

Code Sample: AdvancedSelects/Demos/Functions-String2.sql

-- Select the first 10 characters of each customer's address

/******************************
SQL Server and MySQL
******************************/
SELECT SUBSTRING(Address,1,10)
FROM Customers;

/******************************
Oracle
******************************/
SELECT SUBSTR(Address,1,10)
FROM Customers;
Code Explanation

The above SELECT statement will return the following results (not all rows shown):

Common Date Functions

Common Date Functions
Description SQL Server Oracle MySQL
Date addition DATEADD (use +) DATE_ADD
Date subtraction DATEDIFF (use -) DATEDIFF
Convert date to string DATENAME TO_CHAR DATE_FORMAT
Convert date to number DATEPART TO_NUMBER(TO_CHAR) EXTRACT
Get current date and time GETDATE SYS_DATE NOW

Code Sample: AdvancedSelects/Demos/Functions-Date1.sql

-- Find the hiring age of each employee

/******************************
SQL Server
******************************/
SELECT LastName, BirthDate, HireDate, DATEDIFF(year,BirthDate,HireDate) AS HireAge
FROM Employees
ORDER BY HireAge;

/******************************
Oracle
******************************/
SELECT  LastName, BirthDate, HireDate, FLOOR((HireDate - BirthDate)/365.25) AS HireAge
FROM Employees
ORDER BY HireAge;

/******************************
MySQL
******************************/
-- Find the hiring age of each employee
-- in versions of MySQL prior to 4.1.1
SELECT LastName, BirthDate, HireDate, YEAR(HireDate)-YEAR(BirthDate) AS HireAge
FROM Employees;

-- In MySQL 4.1.1 and later, DATEDIFF() returns the number of days between
-- two dates. You can then divide and floor to get age.
SELECT LastName, BirthDate, HireDate, FLOOR(DATEDIFF(HireDate,BirthDate)/365) AS HireAge
FROM Employees
ORDER BY HireAge;
Code Explanation

The above SELECT statement will return the following results in SQL Server:

And like this in Oracle:

Note for SQL Server users: SQL Server is subtracting the year the employee was born from the year (s)he was hired. This does not give us an accurate age. We'll fix this in an upcoming exercise.

Code Sample: AdvancedSelects/Demos/Functions-Date2.sql

-- Find the Birth month for every employee

/******************************
SQL Server
******************************/
SELECT FirstName, LastName, DATENAME(month,BirthDate) AS BirthMonth
FROM Employees
ORDER BY DATEPART(month,BirthDate);

/******************************
Oracle
******************************/
SELECT FirstName, LastName, TO_CHAR(BirthDate,'MONTH') AS BirthMonth
FROM Employees
ORDER BY TO_NUMBER(TO_CHAR(BirthDate,'MM'));

/******************************
MySQL
******************************/
SELECT FirstName, LastName, DATE_FORMAT(BirthDate, '%M') AS BirthMonth
FROM Employees
ORDER BY EXTRACT(MONTH FROM BirthDate);
Code Explanation

The above SELECT statement will return the following results:

Advanced SELECTs Conclusion

In this lesson of the SQL tutorial, you have continued to use SELECT to create reports from data stored in a single table. In the next lesson, you will learn to create reports from data in multiple tables.

To continue to learn SQL go to the top of this page and click on the next lesson in this SQL Tutorial's Table of Contents.

Use of this website implies agreement to the following:

Copyright Information

All pages and graphics on this Web site are the property of Webucator, Inc. unless otherwise specified.

None of the content on this website may be redistributed or reproduced in any way, shape, or form without written permission from Webucator, Inc.

No Printing or saving of web pages

This content may not be printed or saved. It is for online use only.


Linking to this website

You may link to any of the pages on this website; however, you may not include the content in a frame or iframe without written permission from Webucator, Inc.


Warranties

This website is provided without warranty of any kind. There are no guarantees that use of the site will not be subject to interruptions. All direct or indirect risk related to use of the site is borne entirely by the user. All code and explanations provided on this site are provided without warranties to correctness, performance, fitness, merchantability, and/or any other warranty (whether expressed or implied).

For individual private use only

You agree not to use this online manual to deliver or receive training. If you are delivering or attending a class that is making use of this online manual, you are in violation of our terms of service. Please report any abuse to courseware@webucator.com. If you would like to deliver or receive training using this manual, please fill out the form at http://www.webucator.com/Contact.cfm.