What if you could find the first unique record per group with just one simple command?
Why DISTINCT ON for unique per group in PostgreSQL? - Purpose & Use Cases
Imagine you have a big list of orders from many customers, and you want to find just the first order each customer made. Doing this by hand means scanning through all orders, checking each customer, and picking the earliest one.
Manually sorting and filtering through thousands of orders is slow and tiring. It's easy to make mistakes, like missing some customers or picking the wrong order. This wastes time and causes frustration.
Using DISTINCT ON lets you quickly grab the first unique record per group, like the earliest order per customer, with a simple and clear command. It saves time and avoids errors.
SELECT * FROM orders WHERE order_id IN (SELECT MIN(order_id) FROM orders GROUP BY customer_id);
SELECT DISTINCT ON (customer_id) * FROM orders ORDER BY customer_id, order_date;
This lets you easily get one unique record per group, making data summaries and reports fast and reliable.
A store wants to send a welcome gift to each customer's first purchase. Using DISTINCT ON, they quickly find each customer's earliest order without complex steps.
Manually finding unique records per group is slow and error-prone.
DISTINCT ON simplifies getting the first unique record per group.
This makes data tasks faster, clearer, and less frustrating.
Practice
DISTINCT ON clause do in PostgreSQL?Solution
Step 1: Understand DISTINCT ON purpose
DISTINCT ONreturns only one row per group defined by the columns inside the parentheses.Step 2: Role of ORDER BY with DISTINCT ON
The row returned per group is the first row according to theORDER BYclause.Final Answer:
It returns one unique row per specified group based on the first row in ORDER BY. -> Option AQuick Check:
DISTINCT ON = unique per group [OK]
- Thinking DISTINCT ON removes all duplicates globally
- Ignoring ORDER BY affects which row is chosen
- Confusing DISTINCT ON with GROUP BY
DISTINCT ON?Solution
Step 1: Check DISTINCT ON syntax
The correct syntax requires parentheses around the column(s) for DISTINCT ON, likeDISTINCT ON (customer_id).Step 2: Verify ORDER BY matches DISTINCT ON
ORDER BY must start with the same columns as DISTINCT ON, herecustomer_id, then order byorder_date DESCto get latest order.Final Answer:
SELECT DISTINCT ON (customer_id) * FROM orders ORDER BY customer_id, order_date DESC; -> Option CQuick Check:
Correct syntax = SELECT DISTINCT ON (customer_id) * FROM orders ORDER BY customer_id, order_date DESC; [OK]
- Omitting parentheses around DISTINCT ON columns
- ORDER BY columns not starting with DISTINCT ON columns
- Using wrong columns in DISTINCT ON
sales with columns region, sale_date, and amount, what will this query return?SELECT DISTINCT ON (region) region, sale_date, amount FROM sales ORDER BY region, sale_date DESC;
Solution
Step 1: Analyze DISTINCT ON and ORDER BY
DISTINCT ON (region) picks one row per region. ORDER BY region, sale_date DESC orders rows by region and then newest sale_date first.Step 2: Determine which row is chosen per group
The first row per region after ordering is the one with the latest sale_date, so that row is returned.Final Answer:
One row per region with the latest sale_date. -> Option AQuick Check:
Latest per group = One row per region with the latest sale_date. [OK]
- Assuming earliest date instead of latest
- Thinking all rows are returned
- Believing syntax error due to ORDER BY
SELECT DISTINCT ON (user_id) user_id, login_time FROM logins ORDER BY login_time ASC;
Solution
Step 1: Check DISTINCT ON and ORDER BY columns
DISTINCT ON (user_id) requires ORDER BY to start withuser_idas the first column.Step 2: Identify mismatch in ORDER BY
ORDER BY only haslogin_time ASC, missinguser_idfirst, causing error.Final Answer:
DISTINCT ON columns must match the first columns in ORDER BY. -> Option DQuick Check:
ORDER BY start matches DISTINCT ON [OK]
- Ignoring ORDER BY column order
- Adding unnecessary GROUP BY
- Thinking ASC/DESC causes error
messages with columns chat_id, message_id, and sent_at. You want to get the most recent message per chat. Which query correctly achieves this?Solution
Step 1: Understand requirement for most recent message per chat
We want one row perchat_idwith the latestsent_at.Step 2: Check each option
SELECT DISTINCT ON (chat_id) chat_id, message_id, sent_at FROM messages ORDER BY chat_id, sent_at DESC; uses DISTINCT ON (chat_id) with ORDER BY chat_id, sent_at DESC, which returns the latest message per chat. SELECT DISTINCT ON (message_id) chat_id, message_id, sent_at FROM messages ORDER BY sent_at DESC; uses DISTINCT ON (message_id), which is unique per message, not per chat. SELECT chat_id, MAX(sent_at) FROM messages GROUP BY chat_id; returns only chat_id and max sent_at, missing message_id. SELECT chat_id, message_id, sent_at FROM messages WHERE sent_at = MAX(sent_at) GROUP BY chat_id; has invalid syntax mixing WHERE and GROUP BY incorrectly.Final Answer:
SELECT DISTINCT ON (chat_id) chat_id, message_id, sent_at FROM messages ORDER BY chat_id, sent_at DESC; -> Option BQuick Check:
Latest per group with DISTINCT ON = SELECT DISTINCT ON (chat_id) chat_id, message_id, sent_at FROM messages ORDER BY chat_id, sent_at DESC; [OK]
- Using DISTINCT ON on wrong column
- Trying GROUP BY without selecting all columns
- Incorrect WHERE with aggregate functions
Ready to prove it?
Pass the test and this pattern moves unknown
