Joins and Groups

Joins and GROUP BY go well together: the join puts the data from several tables into rows, and GROUP BY sums them up. How many copies of the games of each genre have customers ordered? The quantities are in order_items, the genres in games:

SELECT g.genre, SUM(i.quantity) AS copies
FROM order_items AS i
JOIN games AS g ON i.game_id = g.id
GROUP BY g.genre
ORDER BY copies DESC, g.genre;
genrecopies
Action8
RPG7
Strategy7
……

The join gives a row for each item, with the genre of its game. GROUP BY then makes a group for each genre, and SUM adds up the quantities in each group.

Money works the same way. An item brought in its quantity times the price the customer paid for one copy: i.quantity * i.price. Not g.price: that's the price in the catalog, and in a sale, customers pay less. The money a group brought in, its revenue, is then SUM(i.quantity * i.price): SUM works out the expression for each row of the group and adds the results up.

When you group by something that has a name, such as a customer or a game, group by its id and add the name to GROUP BY too: GROUP BY c.id, c.name. Two customers can have the same name, and GROUP BY c.name alone would put them into one group, as if they were one person. Thanks to the name in GROUP BY, you can show it in SELECT: each group has one id, so it has one name as well. How many reviews has each customer written, and how many stars do they give on average?

SELECT c.name, COUNT(*) AS review_count, ROUND(AVG(r.stars), 1) AS average
FROM reviews AS r
JOIN customers AS c ON r.customer_id = c.id
GROUP BY c.id, c.name
ORDER BY review_count DESC, c.name;
namereview_countaverage
Emma Clark54.4
Ava Green23.5
Grace Hall23.5
………

A refunded order brought in nothing, so revenue should count only the paid ones. The status is in orders: join it too, and keep only the paid orders with WHERE. WHERE runs before GROUP BY, so the rows of refunded orders are gone before anything is added up. HAVING then picks groups, as you know from the previous lesson.

Typical mistake: SUM(quantity * price) without the aliases. When games is in the query, price is ambiguous, and you get an error. SUM(i.quantity * g.price) is worse: it runs, but it adds up the prices from the catalog, and the sale disappears from the revenue.

Instructions

Show the revenue of each game from paid orders: the title and the revenue as revenue. You need three tables: order_items, orders (for the status) and games. Sort the games by revenue from the highest, then by title:

titlerevenue
Knight's Oath180
Dragon Forge160
Goal Rush100
Ice Hockey Pro90
Turbo Karts90
Zombie Town80
……

Below it, show how many paid orders each customer has placed: the name and the number as order_count, sorted by order_count from the highest, then by name:

nameorder_count
Emma Clark4
Olivia Brown4
Liam Turner3
Noah Wilson3
Ava Green2
……

And which customers have spent more than $100 in paid orders? Show the name and the money they spent as spent, only for the customers who spent more than 100, sorted by spent from the highest, then by name:

namespent
Emma Clark200
Liam Turner150
Noah Wilson150
Olivia Brown150

Start programming for free

By signing up, you agree to the Terms of Service and Privacy Policy.

Or sign up with:

6/12