Chapter 19: PostgreSQL SELECT DISTINCT
Part 1: What is SELECT DISTINCT?
The SELECT DISTINCT clause removes duplicate rows from your query results, returning only unique combinations of the selected columns.
The Basic Syntax
|
0 1 2 3 4 5 6 7 |
<span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> column1<span class="token punctuation">,</span> column2<span class="token punctuation">,</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token keyword">FROM</span> table_name<span class="token punctuation">;</span> |
When you use DISTINCT, PostgreSQL compares each row of your result set and eliminates duplicates, showing each unique combination only once.
DISTINCT vs. ALL
By default, SELECT includes ALL (though we rarely write it explicitly):
|
0 1 2 3 4 5 6 7 8 9 10 11 |
<span class="token comment">-- These are the same:</span> <span class="token keyword">SELECT</span> <span class="token keyword">column</span> <span class="token keyword">FROM</span> <span class="token keyword">table</span><span class="token punctuation">;</span> <span class="token keyword">SELECT</span> <span class="token keyword">ALL</span> <span class="token keyword">column</span> <span class="token keyword">FROM</span> <span class="token keyword">table</span><span class="token punctuation">;</span> <span class="token comment">-- Explicitly includes duplicates</span> <span class="token comment">-- This removes duplicates:</span> <span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> <span class="token keyword">column</span> <span class="token keyword">FROM</span> <span class="token keyword">table</span><span class="token punctuation">;</span> |
Part 2: Setting Up Our Example Data
Let’s create a rich dataset to explore all the nuances of DISTINCT. Imagine we’re running an online store and tracking customer orders:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
<span class="token comment">-- Create a detailed orders table</span> <span class="token keyword">CREATE</span> <span class="token keyword">TABLE</span> orders <span class="token punctuation">(</span> order_id <span class="token keyword">SERIAL</span> <span class="token keyword">PRIMARY</span> <span class="token keyword">KEY</span><span class="token punctuation">,</span> customer_name <span class="token keyword">VARCHAR</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">,</span> customer_city <span class="token keyword">VARCHAR</span><span class="token punctuation">(</span><span class="token number">50</span><span class="token punctuation">)</span><span class="token punctuation">,</span> customer_state <span class="token keyword">VARCHAR</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">,</span> product_category <span class="token keyword">VARCHAR</span><span class="token punctuation">(</span><span class="token number">50</span><span class="token punctuation">)</span><span class="token punctuation">,</span> product_name <span class="token keyword">VARCHAR</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">,</span> quantity <span class="token keyword">INTEGER</span><span class="token punctuation">,</span> order_date <span class="token keyword">DATE</span><span class="token punctuation">,</span> shipping_method <span class="token keyword">VARCHAR</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">,</span> payment_method <span class="token keyword">VARCHAR</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">,</span> order_status <span class="token keyword">VARCHAR</span><span class="token punctuation">(</span><span class="token number">20</span><span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">-- Insert diverse sample data with intentional duplicates</span> <span class="token keyword">INSERT</span> <span class="token keyword">INTO</span> orders <span class="token punctuation">(</span>customer_name<span class="token punctuation">,</span> customer_city<span class="token punctuation">,</span> customer_state<span class="token punctuation">,</span> product_category<span class="token punctuation">,</span> product_name<span class="token punctuation">,</span> quantity<span class="token punctuation">,</span> order_date<span class="token punctuation">,</span> shipping_method<span class="token punctuation">,</span> payment_method<span class="token punctuation">,</span> order_status<span class="token punctuation">)</span> <span class="token keyword">VALUES</span> <span class="token comment">-- Same customer, multiple orders</span> <span class="token punctuation">(</span><span class="token string">'Alice Johnson'</span><span class="token punctuation">,</span> <span class="token string">'Austin'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Electronics'</span><span class="token punctuation">,</span> <span class="token string">'Laptop'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'2024-01-15'</span><span class="token punctuation">,</span> <span class="token string">'Express'</span><span class="token punctuation">,</span> <span class="token string">'Credit Card'</span><span class="token punctuation">,</span> <span class="token string">'Delivered'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Alice Johnson'</span><span class="token punctuation">,</span> <span class="token string">'Austin'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Electronics'</span><span class="token punctuation">,</span> <span class="token string">'Mouse'</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'2024-01-20'</span><span class="token punctuation">,</span> <span class="token string">'Standard'</span><span class="token punctuation">,</span> <span class="token string">'Credit Card'</span><span class="token punctuation">,</span> <span class="token string">'Delivered'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Alice Johnson'</span><span class="token punctuation">,</span> <span class="token string">'Austin'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Accessories'</span><span class="token punctuation">,</span> <span class="token string">'Mouse Pad'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'2024-02-01'</span><span class="token punctuation">,</span> <span class="token string">'Standard'</span><span class="token punctuation">,</span> <span class="token string">'PayPal'</span><span class="token punctuation">,</span> <span class="token string">'Shipped'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">-- Multiple customers in same city</span> <span class="token punctuation">(</span><span class="token string">'Bob Smith'</span><span class="token punctuation">,</span> <span class="token string">'Austin'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Books'</span><span class="token punctuation">,</span> <span class="token string">'SQL Guide'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'2024-01-18'</span><span class="token punctuation">,</span> <span class="token string">'Standard'</span><span class="token punctuation">,</span> <span class="token string">'Debit Card'</span><span class="token punctuation">,</span> <span class="token string">'Delivered'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Carol White'</span><span class="token punctuation">,</span> <span class="token string">'Austin'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Books'</span><span class="token punctuation">,</span> <span class="token string">'Python Book'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'2024-01-22'</span><span class="token punctuation">,</span> <span class="token string">'Express'</span><span class="token punctuation">,</span> <span class="token string">'Credit Card'</span><span class="token punctuation">,</span> <span class="token string">'Delivered'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">-- Customers in different cities</span> <span class="token punctuation">(</span><span class="token string">'David Brown'</span><span class="token punctuation">,</span> <span class="token string">'Dallas'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Electronics'</span><span class="token punctuation">,</span> <span class="token string">'Headphones'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'2024-01-25'</span><span class="token punctuation">,</span> <span class="token string">'Standard'</span><span class="token punctuation">,</span> <span class="token string">'PayPal'</span><span class="token punctuation">,</span> <span class="token string">'Shipped'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Eva Green'</span><span class="token punctuation">,</span> <span class="token string">'Houston'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Home'</span><span class="token punctuation">,</span> <span class="token string">'Blender'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'2024-02-05'</span><span class="token punctuation">,</span> <span class="token string">'Express'</span><span class="token punctuation">,</span> <span class="token string">'Credit Card'</span><span class="token punctuation">,</span> <span class="token string">'Processing'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Frank Black'</span><span class="token punctuation">,</span> <span class="token string">'San Antonio'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Sports'</span><span class="token punctuation">,</span> <span class="token string">'Yoga Mat'</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'2024-02-10'</span><span class="token punctuation">,</span> <span class="token string">'Standard'</span><span class="token punctuation">,</span> <span class="token string">'Debit Card'</span><span class="token punctuation">,</span> <span class="token string">'Pending'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">-- Multiple orders of same product</span> <span class="token punctuation">(</span><span class="token string">'Grace Lee'</span><span class="token punctuation">,</span> <span class="token string">'Austin'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Electronics'</span><span class="token punctuation">,</span> <span class="token string">'Mouse'</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token string">'2024-02-12'</span><span class="token punctuation">,</span> <span class="token string">'Standard'</span><span class="token punctuation">,</span> <span class="token string">'Credit Card'</span><span class="token punctuation">,</span> <span class="token string">'Shipped'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Henry Ford'</span><span class="token punctuation">,</span> <span class="token string">'Dallas'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Electronics'</span><span class="token punctuation">,</span> <span class="token string">'Mouse'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'2024-02-15'</span><span class="token punctuation">,</span> <span class="token string">'Express'</span><span class="token punctuation">,</span> <span class="token string">'PayPal'</span><span class="token punctuation">,</span> <span class="token string">'Delivered'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">-- Duplicate payment methods</span> <span class="token punctuation">(</span><span class="token string">'Iris West'</span><span class="token punctuation">,</span> <span class="token string">'Houston'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Clothing'</span><span class="token punctuation">,</span> <span class="token string">'T-Shirt'</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'2024-02-18'</span><span class="token punctuation">,</span> <span class="token string">'Standard'</span><span class="token punctuation">,</span> <span class="token string">'Credit Card'</span><span class="token punctuation">,</span> <span class="token string">'Delivered'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Jack Ryan'</span><span class="token punctuation">,</span> <span class="token string">'Austin'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Clothing'</span><span class="token punctuation">,</span> <span class="token string">'Jeans'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'2024-02-20'</span><span class="token punctuation">,</span> <span class="token string">'Standard'</span><span class="token punctuation">,</span> <span class="token string">'Credit Card'</span><span class="token punctuation">,</span> <span class="token string">'Delivered'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token comment">-- Different statuses</span> <span class="token punctuation">(</span><span class="token string">'Kate Moss'</span><span class="token punctuation">,</span> <span class="token string">'Dallas'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Beauty'</span><span class="token punctuation">,</span> <span class="token string">'Perfume'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'2024-02-22'</span><span class="token punctuation">,</span> <span class="token string">'Express'</span><span class="token punctuation">,</span> <span class="token string">'PayPal'</span><span class="token punctuation">,</span> <span class="token string">'Pending'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Leo King'</span><span class="token punctuation">,</span> <span class="token string">'Houston'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Beauty'</span><span class="token punctuation">,</span> <span class="token string">'Lotion'</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'2024-02-25'</span><span class="token punctuation">,</span> <span class="token string">'Standard'</span><span class="token punctuation">,</span> <span class="token string">'Debit Card'</span><span class="token punctuation">,</span> <span class="token string">'Processing'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Mona Lisa'</span><span class="token punctuation">,</span> <span class="token string">'Austin'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Art'</span><span class="token punctuation">,</span> <span class="token string">'Paint Set'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'2024-02-28'</span><span class="token punctuation">,</span> <span class="token string">'Express'</span><span class="token punctuation">,</span> <span class="token string">'Credit Card'</span><span class="token punctuation">,</span> <span class="token string">'Shipped'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Part 3: Basic DISTINCT Usage
1. Distinct Values in a Single Column
Let’s find all the unique customer states:
|
0 1 2 3 4 5 6 7 8 |
<span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> customer_state <span class="token keyword">FROM</span> orders <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> customer_state<span class="token punctuation">;</span> |
Result:
| customer_state |
|---|
| TX |
Since all our customers are in Texas, we get just one row. Not very exciting, but it shows how DISTINCT collapses duplicates.
2. Distinct Customer Cities
|
0 1 2 3 4 5 6 7 8 |
<span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> customer_city <span class="token keyword">FROM</span> orders <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> customer_city<span class="token punctuation">;</span> |
Result:
| customer_city |
|---|
| Austin |
| Dallas |
| Houston |
| San Antonio |
Even though Austin appears many times in the table, DISTINCT shows it only once.
3. Counting Distinct Values
Often, we want to know how many distinct values exist:
|
0 1 2 3 4 5 6 7 8 9 10 11 |
<span class="token keyword">SELECT</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> customer_city<span class="token punctuation">)</span> <span class="token keyword">AS</span> unique_cities<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> customer_state<span class="token punctuation">)</span> <span class="token keyword">AS</span> unique_states<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> product_category<span class="token punctuation">)</span> <span class="token keyword">AS</span> unique_categories<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> shipping_method<span class="token punctuation">)</span> <span class="token keyword">AS</span> shipping_methods <span class="token keyword">FROM</span> orders<span class="token punctuation">;</span> |
Result:
| unique_cities | unique_states | unique_categories | shipping_methods |
|---|---|---|---|
| 4 | 1 | 7 | 2 |
This tells us we have customers in 4 different cities (all in Texas), selling products from 7 categories, using 2 shipping methods.
Part 4: DISTINCT on Multiple Columns
Here’s where DISTINCT gets really powerful. When you specify multiple columns, DISTINCT considers the combination of values across those columns.
1. Unique Customer Locations
Find all unique combinations of customer city and state:
|
0 1 2 3 4 5 6 7 8 9 10 |
<span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> customer_city<span class="token punctuation">,</span> customer_state <span class="token keyword">FROM</span> orders <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> customer_city<span class="token punctuation">;</span> |
Result:
| customer_city | customer_state |
|---|---|
| Austin | TX |
| Dallas | TX |
| Houston | TX |
| San Antonio | TX |
This shows each unique city-state pair. If we later had customers from different states with the same city name, we’d see multiple rows for that city.
2. Unique Product Orders
Find all unique combinations of product category and product name:
|
0 1 2 3 4 5 6 7 8 9 10 |
<span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> product_category<span class="token punctuation">,</span> product_name <span class="token keyword">FROM</span> orders <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> product_category<span class="token punctuation">,</span> product_name<span class="token punctuation">;</span> |
Result:
| product_category | product_name |
|---|---|
| Accessories | Mouse Pad |
| Art | Paint Set |
| Beauty | Lotion |
| Beauty | Perfume |
| Books | Python Book |
| Books | SQL Guide |
| Clothing | Jeans |
| Clothing | T-Shirt |
| Electronics | Headphones |
| Electronics | Laptop |
| Electronics | Mouse |
| Home | Blender |
| Sports | Yoga Mat |
Even though “Mouse” appears in multiple orders, it appears only once here because the combination (Electronics, Mouse) is unique.
3. Understanding the Combination Logic
This is crucial: DISTINCT looks at the entire row of selected columns. For example:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
<span class="token comment">-- This looks for unique combinations of (city, state, product_category)</span> <span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> customer_city<span class="token punctuation">,</span> customer_state<span class="token punctuation">,</span> product_category <span class="token keyword">FROM</span> orders <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> customer_city<span class="token punctuation">,</span> product_category<span class="token punctuation">;</span> |
Partial Result:
| customer_city | customer_state | product_category |
|---|---|---|
| Austin | TX | Accessories |
| Austin | TX | Art |
| Austin | TX | Books |
| Austin | TX | Clothing |
| Austin | TX | Electronics |
| Dallas | TX | Beauty |
| Dallas | TX | Electronics |
| … | … | … |
This shows which product categories have been ordered from each city.
Part 5: DISTINCT with NULL Values
NULL values have special behavior with DISTINCT. PostgreSQL treats all NULLs as equal for DISTINCT purposes.
Let’s add some NULL values to see this:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span class="token comment">-- Add some orders with missing shipping method</span> <span class="token keyword">INSERT</span> <span class="token keyword">INTO</span> orders <span class="token punctuation">(</span>customer_name<span class="token punctuation">,</span> customer_city<span class="token punctuation">,</span> customer_state<span class="token punctuation">,</span> product_category<span class="token punctuation">,</span> product_name<span class="token punctuation">,</span> quantity<span class="token punctuation">,</span> order_date<span class="token punctuation">,</span> shipping_method<span class="token punctuation">,</span> payment_method<span class="token punctuation">,</span> order_status<span class="token punctuation">)</span> <span class="token keyword">VALUES</span> <span class="token punctuation">(</span><span class="token string">'Null Test 1'</span><span class="token punctuation">,</span> <span class="token string">'Austin'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Test'</span><span class="token punctuation">,</span> <span class="token string">'Item 1'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'2024-03-01'</span><span class="token punctuation">,</span> <span class="token boolean">NULL</span><span class="token punctuation">,</span> <span class="token string">'Cash'</span><span class="token punctuation">,</span> <span class="token string">'Pending'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Null Test 2'</span><span class="token punctuation">,</span> <span class="token string">'Austin'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Test'</span><span class="token punctuation">,</span> <span class="token string">'Item 2'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'2024-03-02'</span><span class="token punctuation">,</span> <span class="token boolean">NULL</span><span class="token punctuation">,</span> <span class="token string">'Cash'</span><span class="token punctuation">,</span> <span class="token string">'Pending'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Null Test 3'</span><span class="token punctuation">,</span> <span class="token string">'Dallas'</span><span class="token punctuation">,</span> <span class="token string">'TX'</span><span class="token punctuation">,</span> <span class="token string">'Test'</span><span class="token punctuation">,</span> <span class="token string">'Item 3'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'2024-03-03'</span><span class="token punctuation">,</span> <span class="token boolean">NULL</span><span class="token punctuation">,</span> <span class="token string">'Cash'</span><span class="token punctuation">,</span> <span class="token string">'Pending'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">-- Now look at distinct shipping methods</span> <span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> shipping_method <span class="token keyword">FROM</span> orders <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> shipping_method<span class="token punctuation">;</span> |
Result:
| shipping_method |
|---|
| Express |
| Standard |
| NULL |
Notice: all three NULL values collapsed into a single NULL row. This is important – DISTINCT treats all NULLs as identical.
Part 6: DISTINCT ON – PostgreSQL’s Special Feature
PostgreSQL offers a powerful extension to standard SQL: DISTINCT ON. This keeps the “first” row for each unique value in specified columns.
Basic DISTINCT ON Syntax
|
0 1 2 3 4 5 6 7 8 |
<span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> <span class="token keyword">ON</span> <span class="token punctuation">(</span>column1<span class="token punctuation">,</span> column2<span class="token punctuation">,</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">)</span> column1<span class="token punctuation">,</span> column2<span class="token punctuation">,</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> <span class="token keyword">FROM</span> table_name <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> column1<span class="token punctuation">,</span> column2<span class="token punctuation">,</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">;</span> |
⚠️ Critical: The columns in DISTINCT ON must be the first columns in ORDER BY.
Example 1: Latest Order for Each Customer
Find the most recent order for each customer:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> <span class="token keyword">ON</span> <span class="token punctuation">(</span>customer_name<span class="token punctuation">)</span> customer_name<span class="token punctuation">,</span> order_date<span class="token punctuation">,</span> product_name<span class="token punctuation">,</span> quantity<span class="token punctuation">,</span> order_status <span class="token keyword">FROM</span> orders <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> customer_name<span class="token punctuation">,</span> order_date <span class="token keyword">DESC</span><span class="token punctuation">;</span> |
Result:
| customer_name | order_date | product_name | quantity | order_status |
|---|---|---|---|---|
| Alice Johnson | 2024-02-01 | Mouse Pad | 1 | Shipped |
| Bob Smith | 2024-01-18 | SQL Guide | 1 | Delivered |
| Carol White | 2024-01-22 | Python Book | 1 | Delivered |
| David Brown | 2024-01-25 | Headphones | 1 | Shipped |
| Eva Green | 2024-02-05 | Blender | 1 | Processing |
| Frank Black | 2024-02-10 | Yoga Mat | 2 | Pending |
| Grace Lee | 2024-02-12 | Mouse | 3 | Shipped |
| Henry Ford | 2024-02-15 | Mouse | 1 | Delivered |
| Iris West | 2024-02-18 | T-Shirt | 2 | Delivered |
| Jack Ryan | 2024-02-20 | Jeans | 1 | Delivered |
| Kate Moss | 2024-02-22 | Perfume | 1 | Pending |
| Leo King | 2024-02-25 | Lotion | 2 | Processing |
| Mona Lisa | 2024-02-28 | Paint Set | 1 | Shipped |
| Null Test 1 | 2024-03-01 | Item 1 | 1 | Pending |
| Null Test 2 | 2024-03-02 | Item 2 | 1 | Pending |
| Null Test 3 | 2024-03-03 | Item 3 | 1 | Pending |
For Alice Johnson, we see her most recent order (Mouse Pad on 2024-02-01) instead of her earlier orders.
Example 2: Most Expensive Product in Each Category
First, let’s add price information:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<span class="token keyword">ALTER</span> <span class="token keyword">TABLE</span> orders <span class="token keyword">ADD</span> <span class="token keyword">COLUMN</span> price <span class="token keyword">DECIMAL</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">UPDATE</span> orders <span class="token keyword">SET</span> price <span class="token operator">=</span> <span class="token keyword">CASE</span> product_name <span class="token keyword">WHEN</span> <span class="token string">'Laptop'</span> <span class="token keyword">THEN</span> <span class="token number">999.99</span> <span class="token keyword">WHEN</span> <span class="token string">'Mouse'</span> <span class="token keyword">THEN</span> <span class="token number">29.99</span> <span class="token keyword">WHEN</span> <span class="token string">'Mouse Pad'</span> <span class="token keyword">THEN</span> <span class="token number">12.99</span> <span class="token keyword">WHEN</span> <span class="token string">'SQL Guide'</span> <span class="token keyword">THEN</span> <span class="token number">49.99</span> <span class="token keyword">WHEN</span> <span class="token string">'Python Book'</span> <span class="token keyword">THEN</span> <span class="token number">54.99</span> <span class="token keyword">WHEN</span> <span class="token string">'Headphones'</span> <span class="token keyword">THEN</span> <span class="token number">89.99</span> <span class="token keyword">WHEN</span> <span class="token string">'Blender'</span> <span class="token keyword">THEN</span> <span class="token number">129.99</span> <span class="token keyword">WHEN</span> <span class="token string">'Yoga Mat'</span> <span class="token keyword">THEN</span> <span class="token number">24.99</span> <span class="token keyword">WHEN</span> <span class="token string">'T-Shirt'</span> <span class="token keyword">THEN</span> <span class="token number">19.99</span> <span class="token keyword">WHEN</span> <span class="token string">'Jeans'</span> <span class="token keyword">THEN</span> <span class="token number">59.99</span> <span class="token keyword">WHEN</span> <span class="token string">'Perfume'</span> <span class="token keyword">THEN</span> <span class="token number">79.99</span> <span class="token keyword">WHEN</span> <span class="token string">'Lotion'</span> <span class="token keyword">THEN</span> <span class="token number">14.99</span> <span class="token keyword">WHEN</span> <span class="token string">'Paint Set'</span> <span class="token keyword">THEN</span> <span class="token number">34.99</span> <span class="token keyword">ELSE</span> <span class="token number">9.99</span> <span class="token keyword">END</span><span class="token punctuation">;</span> |
Now find the most expensive product in each category:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
<span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> <span class="token keyword">ON</span> <span class="token punctuation">(</span>product_category<span class="token punctuation">)</span> product_category<span class="token punctuation">,</span> product_name<span class="token punctuation">,</span> price <span class="token keyword">FROM</span> orders <span class="token keyword">WHERE</span> price <span class="token operator">IS</span> <span class="token operator">NOT</span> <span class="token boolean">NULL</span> <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> product_category<span class="token punctuation">,</span> price <span class="token keyword">DESC</span><span class="token punctuation">;</span> |
Result:
| product_category | product_name | price |
|---|---|---|
| Accessories | Mouse Pad | 12.99 |
| Art | Paint Set | 34.99 |
| Beauty | Perfume | 79.99 |
| Books | Python Book | 54.99 |
| Clothing | Jeans | 59.99 |
| Electronics | Laptop | 999.99 |
| Home | Blender | 129.99 |
| Sports | Yoga Mat | 24.99 |
| Test | Item 1 | 9.99 |
For each category, we get the product with the highest price.
Part 7: DISTINCT vs. GROUP BY
Often, you can achieve similar results with DISTINCT and GROUP BY. Understanding the difference helps you choose the right tool.
Same Result, Different Approaches
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="token comment">-- Using DISTINCT</span> <span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> customer_city<span class="token punctuation">,</span> customer_state <span class="token keyword">FROM</span> orders<span class="token punctuation">;</span> <span class="token comment">-- Using GROUP BY</span> <span class="token keyword">SELECT</span> customer_city<span class="token punctuation">,</span> customer_state <span class="token keyword">FROM</span> orders <span class="token keyword">GROUP</span> <span class="token keyword">BY</span> customer_city<span class="token punctuation">,</span> customer_state<span class="token punctuation">;</span> |
Both return the same unique city-state combinations.
When GROUP BY is Better
GROUP BY becomes essential when you need aggregations:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="token comment">-- Can't do this with DISTINCT</span> <span class="token keyword">SELECT</span> customer_city<span class="token punctuation">,</span> customer_state<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">)</span> <span class="token keyword">AS</span> order_count<span class="token punctuation">,</span> <span class="token function">AVG</span><span class="token punctuation">(</span>quantity<span class="token punctuation">)</span> <span class="token keyword">AS</span> avg_quantity <span class="token keyword">FROM</span> orders <span class="token keyword">GROUP</span> <span class="token keyword">BY</span> customer_city<span class="token punctuation">,</span> customer_state<span class="token punctuation">;</span> |
Result:
| customer_city | customer_state | order_count | avg_quantity |
|---|---|---|---|
| Austin | TX | 8 | 1.3750 |
| Dallas | TX | 3 | 1.0000 |
| Houston | TX | 3 | 1.3333 |
| San Antonio | TX | 1 | 2.0000 |
Performance Considerations
-
DISTINCTis often optimized for simple uniqueness checks -
GROUP BYis optimized for aggregations but can be used for uniqueness -
For large datasets, test both approaches to see which performs better
Part 8: Real-World Examples
Example 1: Customer Analytics Dashboard
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<span class="token keyword">SELECT</span> <span class="token comment">-- Basic customer demographics</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> customer_name<span class="token punctuation">)</span> <span class="token keyword">AS</span> unique_customers<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> customer_city<span class="token punctuation">)</span> <span class="token keyword">AS</span> cities_served<span class="token punctuation">,</span> <span class="token comment">-- Purchase patterns</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> product_category<span class="token punctuation">)</span> <span class="token keyword">AS</span> categories_purchased<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> <span class="token keyword">CASE</span> <span class="token keyword">WHEN</span> order_status <span class="token operator">=</span> <span class="token string">'Delivered'</span> <span class="token keyword">THEN</span> order_id <span class="token keyword">END</span><span class="token punctuation">)</span> <span class="token keyword">AS</span> completed_orders<span class="token punctuation">,</span> <span class="token comment">-- Payment preferences</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> payment_method<span class="token punctuation">)</span> <span class="token keyword">AS</span> payment_methods_used<span class="token punctuation">,</span> <span class="token comment">-- Geographic distribution</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> customer_state<span class="token punctuation">)</span> <span class="token keyword">AS</span> states_served<span class="token punctuation">,</span> <span class="token comment">-- Average order value (requires price data)</span> <span class="token function">ROUND</span><span class="token punctuation">(</span><span class="token function">AVG</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> price<span class="token punctuation">)</span>::<span class="token keyword">numeric</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token keyword">AS</span> avg_unique_product_price <span class="token keyword">FROM</span> orders<span class="token punctuation">;</span> |
Example 2: Inventory Planning Report
Find which product categories are sold in each city:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
<span class="token keyword">SELECT</span> customer_city<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> product_category<span class="token punctuation">)</span> <span class="token keyword">AS</span> category_count<span class="token punctuation">,</span> STRING_AGG<span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> product_category<span class="token punctuation">,</span> <span class="token string">', '</span> <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> product_category<span class="token punctuation">)</span> <span class="token keyword">AS</span> categories <span class="token keyword">FROM</span> orders <span class="token keyword">GROUP</span> <span class="token keyword">BY</span> customer_city <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> category_count <span class="token keyword">DESC</span><span class="token punctuation">;</span> |
Result:
| customer_city | category_count | categories |
|---|---|---|
| Austin | 5 | Accessories, Art, Books, Clothing, Electronics |
| Dallas | 3 | Beauty, Electronics, Test |
| Houston | 3 | Beauty, Clothing, Home |
| San Antonio | 1 | Sports |
Example 3: Shipping Method Analysis
Analyze shipping methods by city and status:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<span class="token keyword">SELECT</span> customer_city<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> shipping_method<span class="token punctuation">)</span> <span class="token keyword">AS</span> shipping_options_used<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> order_status<span class="token punctuation">)</span> <span class="token keyword">AS</span> statuses_encountered<span class="token punctuation">,</span> STRING_AGG<span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> order_status<span class="token punctuation">,</span> <span class="token string">', '</span><span class="token punctuation">)</span> <span class="token keyword">AS</span> all_statuses <span class="token keyword">FROM</span> orders <span class="token keyword">WHERE</span> shipping_method <span class="token operator">IS</span> <span class="token operator">NOT</span> <span class="token boolean">NULL</span> <span class="token keyword">GROUP</span> <span class="token keyword">BY</span> customer_city <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> shipping_options_used <span class="token keyword">DESC</span><span class="token punctuation">;</span> |
Example 4: Customer Purchase History Summary
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span class="token keyword">SELECT</span> customer_name<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> order_date<span class="token punctuation">)</span> <span class="token keyword">AS</span> different_days_ordered<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> product_category<span class="token punctuation">)</span> <span class="token keyword">AS</span> categories_bought<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> product_name<span class="token punctuation">)</span> <span class="token keyword">AS</span> unique_products<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> <span class="token keyword">CASE</span> <span class="token keyword">WHEN</span> order_status <span class="token operator">=</span> <span class="token string">'Delivered'</span> <span class="token keyword">THEN</span> order_id <span class="token keyword">END</span><span class="token punctuation">)</span> <span class="token keyword">AS</span> successful_orders<span class="token punctuation">,</span> <span class="token function">MIN</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> order_date<span class="token punctuation">)</span> <span class="token keyword">AS</span> first_order<span class="token punctuation">,</span> <span class="token function">MAX</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> order_date<span class="token punctuation">)</span> <span class="token keyword">AS</span> last_order <span class="token keyword">FROM</span> orders <span class="token keyword">GROUP</span> <span class="token keyword">BY</span> customer_name <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> different_days_ordered <span class="token keyword">DESC</span><span class="token punctuation">,</span> unique_products <span class="token keyword">DESC</span><span class="token punctuation">;</span> |
Part 9: DISTINCT with Window Functions
Advanced users can combine DISTINCT with window functions for sophisticated analytics:
Running Count of Distinct Customers
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<span class="token keyword">SELECT</span> order_date<span class="token punctuation">,</span> customer_name<span class="token punctuation">,</span> product_name<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> customer_name<span class="token punctuation">)</span> <span class="token keyword">OVER</span> <span class="token punctuation">(</span> <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> order_date <span class="token keyword">ROWS</span> <span class="token operator">BETWEEN</span> <span class="token keyword">UNBOUNDED</span> <span class="token keyword">PRECEDING</span> <span class="token operator">AND</span> <span class="token keyword">CURRENT</span> <span class="token keyword">ROW</span> <span class="token punctuation">)</span> <span class="token keyword">AS</span> unique_customers_so_far <span class="token keyword">FROM</span> orders <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> order_date<span class="token punctuation">;</span> |
Distinct Products Per Customer Over Time
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span class="token keyword">SELECT</span> customer_name<span class="token punctuation">,</span> order_date<span class="token punctuation">,</span> product_name<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">DISTINCT</span> product_category<span class="token punctuation">)</span> <span class="token keyword">OVER</span> <span class="token punctuation">(</span> <span class="token keyword">PARTITION</span> <span class="token keyword">BY</span> customer_name <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> order_date <span class="token keyword">ROWS</span> <span class="token operator">BETWEEN</span> <span class="token keyword">UNBOUNDED</span> <span class="token keyword">PRECEDING</span> <span class="token operator">AND</span> <span class="token keyword">CURRENT</span> <span class="token keyword">ROW</span> <span class="token punctuation">)</span> <span class="token keyword">AS</span> distinct_categories_so_far <span class="token keyword">FROM</span> orders <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> customer_name<span class="token punctuation">,</span> order_date<span class="token punctuation">;</span> |
Part 10: Common Pitfalls and Solutions
Pitfall 1: DISTINCT Doesn’t Work as Expected with ORDER BY
|
0 1 2 3 4 5 6 7 8 9 |
<span class="token comment">-- ❌ This doesn't guarantee which row is kept</span> <span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> customer_city<span class="token punctuation">,</span> customer_name <span class="token keyword">FROM</span> orders <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> order_date <span class="token keyword">DESC</span><span class="token punctuation">;</span> |
Solution: Use DISTINCT ON with proper ordering:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
<span class="token comment">-- ✅ This keeps the most recent order for each city</span> <span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> <span class="token keyword">ON</span> <span class="token punctuation">(</span>customer_city<span class="token punctuation">)</span> customer_city<span class="token punctuation">,</span> customer_name<span class="token punctuation">,</span> order_date <span class="token keyword">FROM</span> orders <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> customer_city<span class="token punctuation">,</span> order_date <span class="token keyword">DESC</span><span class="token punctuation">;</span> |
Pitfall 2: Forgetting NULLs in DISTINCT
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
<span class="token comment">-- This will include a NULL row if any shipping_method is NULL</span> <span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> shipping_method <span class="token keyword">FROM</span> orders<span class="token punctuation">;</span> <span class="token comment">-- To exclude NULLs</span> <span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> shipping_method <span class="token keyword">FROM</span> orders <span class="token keyword">WHERE</span> shipping_method <span class="token operator">IS</span> <span class="token operator">NOT</span> <span class="token boolean">NULL</span><span class="token punctuation">;</span> |
Pitfall 3: DISTINCT with Large Text Fields
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="token comment">-- This can be very slow on large text columns</span> <span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> product_description <span class="token keyword">FROM</span> products<span class="token punctuation">;</span> <span class="token comment">-- Consider using hash or partial indexes, or </span> <span class="token comment">-- DISTINCT ON a hash of the text instead</span> <span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> <span class="token keyword">ON</span> <span class="token punctuation">(</span>MD5<span class="token punctuation">(</span>product_description::<span class="token keyword">text</span><span class="token punctuation">)</span><span class="token punctuation">)</span> product_description <span class="token keyword">FROM</span> products<span class="token punctuation">;</span> |
Pitfall 4: Assuming DISTINCT Orders Results
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
<span class="token comment">-- The order of results is NOT guaranteed!</span> <span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> customer_city <span class="token keyword">FROM</span> orders<span class="token punctuation">;</span> <span class="token comment">-- Always specify ORDER BY if order matters</span> <span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> customer_city <span class="token keyword">FROM</span> orders <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> customer_city<span class="token punctuation">;</span> |
Part 11: Performance Optimization
Creating Indexes for DISTINCT Queries
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="token comment">-- Index for single column DISTINCT</span> <span class="token keyword">CREATE</span> <span class="token keyword">INDEX</span> idx_orders_customer_city <span class="token keyword">ON</span> orders<span class="token punctuation">(</span>customer_city<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">-- Index for multi-column DISTINCT</span> <span class="token keyword">CREATE</span> <span class="token keyword">INDEX</span> idx_orders_city_state <span class="token keyword">ON</span> orders<span class="token punctuation">(</span>customer_city<span class="token punctuation">,</span> customer_state<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">-- Index for DISTINCT ON queries</span> <span class="token keyword">CREATE</span> <span class="token keyword">INDEX</span> idx_orders_customer_date <span class="token keyword">ON</span> orders<span class="token punctuation">(</span>customer_name<span class="token punctuation">,</span> order_date <span class="token keyword">DESC</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Analyzing Query Performance
Use EXPLAIN ANALYZE to see how PostgreSQL executes your DISTINCT queries:
|
0 1 2 3 4 5 6 7 8 9 |
<span class="token keyword">EXPLAIN</span> <span class="token keyword">ANALYZE</span> <span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> customer_city<span class="token punctuation">,</span> customer_state <span class="token keyword">FROM</span> orders <span class="token keyword">WHERE</span> customer_state <span class="token operator">=</span> <span class="token string">'TX'</span><span class="token punctuation">;</span> |
This shows whether PostgreSQL is using indexes, how many rows it’s processing, and where the time is spent.
Summary: The DISTINCT Philosophy
SELECT DISTINCT is your tool for finding the unique “fingerprints” in your data:
-
Single column DISTINCT – “What are all the unique values in this column?”
-
Multi-column DISTINCT – “What are all the unique combinations of these columns?”
-
DISTINCT ON (PostgreSQL special) – “Give me the first row for each unique key”
-
COUNT(DISTINCT) – “How many unique values exist?”
Remember:
-
DISTINCT removes duplicate rows, not duplicate values in a single column (unless it’s the only column)
-
NULLs are all considered equal for DISTINCT
-
Always use ORDER BY with DISTINCT ON
-
Consider GROUP BY when you need aggregations
-
Test performance on large datasets
The beauty of DISTINCT is that it helps you understand the variety and uniqueness in your data. It answers questions like “How many different cities do our customers come from?” and “What product categories has each customer purchased?”
Master DISTINCT, and you’ll have a powerful lens for viewing the unique patterns hidden in your database!
Would you like me to elaborate on any specific aspect of DISTINCT, such as more complex DISTINCT ON scenarios, performance tuning, or integration with other SQL features?
