More About GROUP BY Clause in MySQL
In last tutorial, we have had a glimpse about how to use Group By clause. In this tutorial, we are going to
look at more closely to the requirements of using Group By clause.
Rows in a table can be grouped by using one or more columns. For example, rows in products table can be
grouped by CategoryID values so that we can see summarized information for each group of the product categories
(e.g. what is the total number of units in stock for each product category). When using Group By clause, consider the
following facts and guidelines:
For each group of rows, a single row of values is produced. See Practice #1.
If WHERE clause is used, only the rows that satisfy the WHERE clause conditions are grouped.
Also, the WHERE clause must be listed before the GROUP BY clause. See Practice #2.
If the column used in GROUP BY clause contains null values, the null values are treated as a group. To exclude this group,
use IS NOT NULL in the WHERE clause. See Practice #3-1, #3-2.
Function(s) other than aggregation functions can be used in GROUP BY clause. See Practice #4
By using GROUP BY clause, rows can be converted to columns which mimics pivot table effect in MS Excel. See Practice #5-1, #5-2
Column alias can be used in GROUP BY clause. This is different to most other database management systems such as Oracle and SQL Server. See Practice #6-1, #6-2, #6-3
Practice #1: A single row of values is produced for each group.
Most of the queries in the tutorials need Northwind MySQL database, you can download the database script on this page.
select c.CategoryID,
c.CategoryName,
sum(UnitsInStock) as "Total units in stock"
from products as p
inner join categories as c on c.CategoryID=p.CategoryID
group by p.CategoryID;
Query result set - 8 rows returned:
Practice #2: Using WHERE clause with GROUP BY.
Most of the queries in the tutorials need Northwind MySQL database, you can download the database script on this page.
select c.CategoryID,
c.CategoryName,
sum(UnitsInStock) as "Total units in stock"
from products as p
inner join categories as c on c.CategoryID=p.CategoryID
where c.CategoryID in (1, 2, 3, 4, 5)
group by p.CategoryID;
Query result set - 5 rows returned:
Practice #3-1: NULL values are treated as a group.
Most of the queries in the tutorials need Northwind MySQL database, you can download the database script on this page.
select ReportsTo, count(*) as Num_of_employees
from employees
group by ReportsTo;
Query result set - 3 rows returned:
Practice #3-2: NULL values are removed.
Most of the queries in the tutorials need Northwind MySQL database, you can download the database script on this page.
select ReportsTo, count(*) as Num_of_employees
from employees
where ReportsTo is not null
group by ReportsTo;
Query result set - 3 rows returned:
Practice #4: Using case statement in GROUP BY clause.
Most of the queries in the tutorials need Northwind MySQL database, you can download the database script on this page.
select c.CategoryName as "Product Category",
case when s.Country in
('UK','Spain','Sweden','Germany','Norway',
'Denmark','Netherlands','Finland','Italy','France')
then 'Europe'
when s.Country in ('USA','Canada','Brazil')
then 'America'
else 'Asia-Pacific'
end as "Supplier Continent",
sum(p.UnitsInStock) as UnitsInStock
from Suppliers as s
inner join Products as p on p.SupplierID=s.SupplierID
inner join Categories as c on c.CategoryID=p.CategoryID
group by c.CategoryName,
case when s.Country in
('UK','Spain','Sweden','Germany','Norway',
'Denmark','Netherlands','Finland','Italy','France')
then 'Europe'
when s.Country in ('USA','Canada','Brazil')
then 'America'
else 'Asia-Pacific'
end;
Query result set - 21 rows returned:
Practice #5-1: Converting rows to columns by using GROUP BY clause.
Most of the queries in the tutorials need Northwind MySQL database, you can download the database script on this page.
select c.CategoryName as "Product Category",
sum(case when s.Country in
('UK','Spain','Sweden','Germany','Norway',
'Denmark','Netherlands','Finland','Italy','France')
then p.UnitsInStock end) as Europe,
sum(case when s.Country in ('USA','Canada','Brazil')
then p.UnitsInStock end) as America,
sum(case when s.Country in ('Japan','Australia','Singapore')
then p.UnitsInStock end) as "Asia-Pacific"
from Suppliers as s
inner join Products as p on p.SupplierID=s.SupplierID
inner join Categories as c on c.CategoryID=p.CategoryID
group by c.CategoryName;
Query result set - 8 rows returned:
Practice #5-2: Converting rows to columns and nulls to zero.
Most of the queries in the tutorials need Northwind MySQL database, you can download the database script on this page.
select c.CategoryName as "Product Category",
ifnull(sum(case when s.Country in
('UK','Spain','Sweden','Germany','Norway',
'Denmark','Netherlands','Finland','Italy','France')
then p.UnitsInStock end), 0) as Europe,
ifnull(sum(case when s.Country in ('USA','Canada','Brazil')
then p.UnitsInStock end), 0) as America,
ifnull(sum(case when s.Country in ('Japan','Australia','Singapore')
then p.UnitsInStock end), 0) as "Asia-Pacific"
from Suppliers as s
inner join Products as p on p.SupplierID=s.SupplierID
inner join Categories as c on c.CategoryID=p.CategoryID
group by c.CategoryName;
Query result set - 8 rows returned:
Practice #6-1: Using column alias in GROUP BY clause.
Most of the queries in the tutorials need Northwind MySQL database, you can download the database script on this page.
select c.CategoryName,
p.ProductName,
concat('Qtr ', quarter(o.ShippedDate)) as ShippedQuarter,
concat('$', round(sum(od.UnitPrice*od.Quantity*(1-od.Discount)), 2))
as ProductSales
from orders as o
inner join order_details as od on o.OrderID = od.OrderID
inner join products as p on od.ProductID = p.ProductID
inner join categories as c on c.CategoryID = p.CategoryID
where o.ShippedDate between '1996-5-1' and '1996-10-31'
group by c.CategoryName, p.ProductName, ShippedQuarter
order by ShippedQuarter, c.CategoryName, p.ProductName;
Query result set - 111 rows returned:
Practice #6-2: Column in select list but not in GROUP BY clause.
Most of the queries in the tutorials need Northwind MySQL database, you can download the database script on this page.
select c.CategoryName,
p.ProductName,
concat('Qtr ', quarter(o.ShippedDate)) as ShippedQuarter,
concat('$', round(sum(od.UnitPrice*od.Quantity*(1-od.Discount)), 2))
as ProductSales
from orders as o
inner join order_details as od on o.OrderID = od.OrderID
inner join products as p on od.ProductID = p.ProductID
inner join categories as c on c.CategoryID = p.CategoryID
where o.ShippedDate between '1996-5-1' and '1996-10-31'
group by c.CategoryName, p.ProductName
order by ShippedQuarter, c.CategoryName, p.ProductName;
Query result set - 71 rows returned:
Practice #6-3: Another pivot table query result.
Most of the queries in the tutorials need Northwind MySQL database, you can download the database script on this page.
select p.ProductName,
c.CompanyName,
year(o.OrderDate) as OrderYear,
ifnull(round(sum(case when quarter(o.OrderDate)=1
then od.UnitPrice*od.Quantity*(1-od.Discount) end), 2), 0)
as Qtr1,
ifnull(round(sum(case when quarter(o.OrderDate)=2
then od.UnitPrice*od.Quantity*(1-od.Discount) end), 2), 0)
as Qtr2,
ifnull(round(sum(case when quarter(o.OrderDate)=3
then od.UnitPrice*od.Quantity*(1-od.Discount) end), 2), 0)
as Qtr3,
ifnull(round(sum(case when quarter(o.OrderDate)=4
then od.UnitPrice*od.Quantity*(1-od.Discount) end), 2), 0)
as Qtr4
from orders as o
inner join customers as c on c.CustomerID=o.CustomerID
inner join order_details as od on od.OrderID=o.OrderID
inner join Products as p on p.ProductID=od.ProductID
where o.OrderDate between '1997-1-1' and '1997-12-31'
group by p.ProductName, c.CustomerID, OrderYear;
Query result set - 947 rows returned:
Other tutorials in this category
1. Using Aggregate Functions and Group By Clause in MySQL
2. Using GROUP BY with HAVING Clause in MySQL
3. Summarizing Data From Multiple Tables in MySQL
4. Summarizing Data From Multiple Tables in MySQL - Part 2
Back to Tutorial Index Page