Chapter 18: PostgreSQL Select Data
Part 1: What is the SELECT Statement?
At its core, the SELECT statement is how you retrieve data from a PostgreSQL database . It’s the “R” in CRUD (Create, Read, Update, Delete) operations. When you use SELECT, you’re asking the database to show you specific information from one or more tables, and it returns that information in a result table called a result set .
The Simplest Form
The most basic SELECT statement has two main parts :
|
0 1 2 3 4 5 6 7 |
<span class="token keyword">SELECT</span> expressions <span class="token keyword">FROM</span> <span class="token keyword">tables</span><span class="token punctuation">;</span> |
-
SELECT: Specifies what columns or calculated values you want to see -
FROM: Specifies which table(s) to get the data from
A Complete Breakdown
Here’s a more complete picture of what a SELECT statement can include :
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="token keyword">SELECT</span> <span class="token punctuation">[</span><span class="token keyword">DISTINCT</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 punctuation">[</span><span class="token keyword">WHERE</span> condition<span class="token punctuation">]</span> <span class="token punctuation">[</span><span class="token keyword">GROUP</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> <span class="token punctuation">[</span><span class="token keyword">HAVING</span> condition<span class="token punctuation">]</span> <span class="token punctuation">[</span><span class="token keyword">ORDER</span> <span class="token keyword">BY</span> column1 <span class="token punctuation">[</span><span class="token keyword">ASC</span> <span class="token operator">|</span> <span class="token keyword">DESC</span><span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token punctuation">[</span><span class="token keyword">LIMIT</span> number_rows<span class="token punctuation">]</span> <span class="token punctuation">[</span><span class="token keyword">OFFSET</span> number_rows<span class="token punctuation">]</span><span class="token punctuation">;</span> |
Don’t worry if this looks overwhelming – we’ll build up to this step by step!
Part 2: Basic SELECT Queries
Let’s start with the fundamentals. Imagine we have a simple table called products:
|
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 comment">-- Create a sample table</span> <span class="token keyword">CREATE</span> <span class="token keyword">TABLE</span> products <span class="token punctuation">(</span> id <span class="token keyword">SERIAL</span> <span class="token keyword">PRIMARY</span> <span class="token keyword">KEY</span><span class="token punctuation">,</span> 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> 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> 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> in_stock <span class="token keyword">BOOLEAN</span><span class="token punctuation">,</span> created_date <span class="token keyword">DATE</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">-- Insert some sample data</span> <span class="token keyword">INSERT</span> <span class="token keyword">INTO</span> products <span class="token punctuation">(</span>name<span class="token punctuation">,</span> category<span class="token punctuation">,</span> price<span class="token punctuation">,</span> in_stock<span class="token punctuation">,</span> created_date<span class="token punctuation">)</span> <span class="token keyword">VALUES</span> <span class="token punctuation">(</span><span class="token string">'Laptop'</span><span class="token punctuation">,</span> <span class="token string">'Electronics'</span><span class="token punctuation">,</span> <span class="token number">999.99</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token string">'2024-01-15'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Desk Chair'</span><span class="token punctuation">,</span> <span class="token string">'Furniture'</span><span class="token punctuation">,</span> <span class="token number">249.50</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token string">'2024-01-20'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Coffee Maker'</span><span class="token punctuation">,</span> <span class="token string">'Appliances'</span><span class="token punctuation">,</span> <span class="token number">79.99</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token string">'2024-02-01'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Notebook'</span><span class="token punctuation">,</span> <span class="token string">'Office Supplies'</span><span class="token punctuation">,</span> <span class="token number">4.99</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token string">'2024-02-10'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Desk Lamp'</span><span class="token punctuation">,</span> <span class="token string">'Furniture'</span><span class="token punctuation">,</span> <span class="token number">45.00</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token string">'2024-02-15'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Mouse'</span><span class="token punctuation">,</span> <span class="token string">'Electronics'</span><span class="token punctuation">,</span> <span class="token number">29.99</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token string">'2024-02-20'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Paper Clips'</span><span class="token punctuation">,</span> <span class="token string">'Office Supplies'</span><span class="token punctuation">,</span> <span class="token number">2.50</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token string">'2024-02-25'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Blender'</span><span class="token punctuation">,</span> <span class="token string">'Appliances'</span><span class="token punctuation">,</span> <span class="token number">129.99</span><span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token string">'2024-03-01'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
1. SELECT All Columns
To see everything in a table, use the asterisk (*) shorthand :
|
0 1 2 3 4 5 6 |
<span class="token keyword">SELECT</span> <span class="token operator">*</span> <span class="token keyword">FROM</span> products<span class="token punctuation">;</span> |
Result:
| id | name | category | price | in_stock | created_date |
|---|---|---|---|---|---|
| 1 | Laptop | Electronics | 999.99 | true | 2024-01-15 |
| 2 | Desk Chair | Furniture | 249.50 | true | 2024-01-20 |
| 3 | Coffee Maker | Appliances | 79.99 | false | 2024-02-01 |
| 4 | Notebook | Office Supplies | 4.99 | true | 2024-02-10 |
| 5 | Desk Lamp | Furniture | 45.00 | true | 2024-02-15 |
| 6 | Mouse | Electronics | 29.99 | true | 2024-02-20 |
| 7 | Paper Clips | Office Supplies | 2.50 | true | 2024-02-25 |
| 8 | Blender | Appliances | 129.99 | false | 2024-03-01 |
⚠️ Important Note: While SELECT * is convenient for quick exploration, it’s considered bad practice in production code . If your table structure changes (columns added or removed), your application might break unexpectedly. Always specify exactly the columns you need.
2. SELECT Specific Columns
To retrieve only certain columns, list them after SELECT :
|
0 1 2 3 4 5 6 |
<span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> price <span class="token keyword">FROM</span> products<span class="token punctuation">;</span> |
Result:
| name | price |
|---|---|
| Laptop | 999.99 |
| Desk Chair | 249.50 |
| Coffee Maker | 79.99 |
| Notebook | 4.99 |
| Desk Lamp | 45.00 |
| Mouse | 29.99 |
| Paper Clips | 2.50 |
| Blender | 129.99 |
This is more efficient – the database only retrieves the data you actually need.
3. SELECT with Expressions and Calculations
You’re not limited to just column names – you can use expressions and calculations :
|
0 1 2 3 4 5 6 7 8 9 10 11 |
<span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> price<span class="token punctuation">,</span> price <span class="token operator">*</span> <span class="token number">1.1</span> <span class="token keyword">AS</span> price_with_tax<span class="token punctuation">,</span> <span class="token comment">-- Add 10% tax</span> price <span class="token operator">*</span> <span class="token number">0.8</span> <span class="token keyword">AS</span> sale_price <span class="token comment">-- 20% off</span> <span class="token keyword">FROM</span> products<span class="token punctuation">;</span> |
Result:
| name | price | price_with_tax | sale_price |
|---|---|---|---|
| Laptop | 999.99 | 1099.989 | 799.992 |
| Desk Chair | 249.50 | 274.45 | 199.60 |
| … | … | … | … |
The AS keyword creates an alias – a temporary name for the calculated column . This makes your results much more readable.
4. SELECT Without a Table (Using PostgreSQL as a Calculator)
Here’s a fun fact – you don’t always need a table! PostgreSQL can evaluate expressions directly :
|
0 1 2 3 4 5 6 7 8 9 10 |
<span class="token keyword">SELECT</span> <span class="token number">6</span> <span class="token operator">*</span> <span class="token number">3</span> <span class="token keyword">AS</span> multiplication<span class="token punctuation">,</span> <span class="token keyword">CURRENT_DATE</span> <span class="token keyword">AS</span> today<span class="token punctuation">,</span> UPPER<span class="token punctuation">(</span><span class="token string">'hello world'</span><span class="token punctuation">)</span> <span class="token keyword">AS</span> uppercase<span class="token punctuation">,</span> RANDOM<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token number">100</span> <span class="token keyword">AS</span> random_number<span class="token punctuation">;</span> |
Result:
| multiplication | today | uppercase | random_number |
|---|---|---|---|
| 18 | 2025-02-13 | HELLO WORLD | 73.4567 |
This is incredibly useful for testing functions or performing quick calculations.
5. Concatenating Columns
You can combine columns using the concatenation operator || :
|
0 1 2 3 4 5 6 7 8 9 |
<span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> <span class="token string">'Product: '</span> <span class="token operator">||</span> name <span class="token operator">||</span> <span class="token string">' - $'</span> <span class="token operator">||</span> price <span class="token keyword">AS</span> product_description <span class="token keyword">FROM</span> products<span class="token punctuation">;</span> |
Result:
| name | product_description |
|---|---|
| Laptop | Product: Laptop – $999.99 |
| Desk Chair | Product: Desk Chair – $249.50 |
| … | … |
Part 3: Filtering Data with WHERE
The real power of SELECT comes when you start filtering. The WHERE clause lets you specify conditions that rows must meet to be included .
1. Basic Equality Filter
|
0 1 2 3 4 5 6 7 8 |
<span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> price<span class="token punctuation">,</span> in_stock <span class="token keyword">FROM</span> products <span class="token keyword">WHERE</span> category <span class="token operator">=</span> <span class="token string">'Electronics'</span><span class="token punctuation">;</span> |
Result:
| name | price | in_stock |
|---|---|---|
| Laptop | 999.99 | true |
| Mouse | 29.99 | true |
2. Comparison Operators
You can use all the usual comparison operators :
|
0 1 2 3 4 5 6 7 8 9 |
<span class="token comment">-- Products costing more than $100</span> <span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> price <span class="token keyword">FROM</span> products <span class="token keyword">WHERE</span> price <span class="token operator">></span> <span class="token number">100</span><span class="token punctuation">;</span> |
Result:
| name | price |
|---|---|
| Laptop | 999.99 |
| Desk Chair | 249.50 |
| Blender | 129.99 |
3. Multiple Conditions with AND/OR
Combine conditions using logical operators :
|
0 1 2 3 4 5 6 7 8 9 10 |
<span class="token comment">-- Electronics that are in stock</span> <span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> price<span class="token punctuation">,</span> category <span class="token keyword">FROM</span> products <span class="token keyword">WHERE</span> category <span class="token operator">=</span> <span class="token string">'Electronics'</span> <span class="token operator">AND</span> in_stock <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> |
Result:
| name | price | category |
|---|---|---|
| Laptop | 999.99 | Electronics |
| Mouse | 29.99 | Electronics |
|
0 1 2 3 4 5 6 7 8 9 10 |
<span class="token comment">-- Either furniture OR office supplies</span> <span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> category<span class="token punctuation">,</span> price <span class="token keyword">FROM</span> products <span class="token keyword">WHERE</span> category <span class="token operator">=</span> <span class="token string">'Furniture'</span> <span class="token operator">OR</span> category <span class="token operator">=</span> <span class="token string">'Office Supplies'</span><span class="token punctuation">;</span> |
Result:
| name | category | price |
|---|---|---|
| Desk Chair | Furniture | 249.50 |
| Notebook | Office Supplies | 4.99 |
| Desk Lamp | Furniture | 45.00 |
| Paper Clips | Office Supplies | 2.50 |
4. Range Conditions with BETWEEN
For ranges, BETWEEN is cleaner than using >= and <= :
|
0 1 2 3 4 5 6 7 8 |
<span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> price <span class="token keyword">FROM</span> products <span class="token keyword">WHERE</span> price <span class="token operator">BETWEEN</span> <span class="token number">50</span> <span class="token operator">AND</span> <span class="token number">200</span><span class="token punctuation">;</span> |
Result:
| name | price |
|---|---|
| Desk Lamp | 45.00 |
| Mouse | 29.99 |
This is equivalent to price >= 50 AND price <= 200.
5. Pattern Matching with LIKE
Use LIKE for text pattern matching :
|
0 1 2 3 4 5 6 7 8 9 |
<span class="token comment">-- Products that start with 'Desk'</span> <span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> category <span class="token keyword">FROM</span> products <span class="token keyword">WHERE</span> name <span class="token operator">LIKE</span> <span class="token string">'Desk%'</span><span class="token punctuation">;</span> |
Result:
| name | category |
|---|---|
| Desk Chair | Furniture |
| Desk Lamp | Furniture |
-
%matches any sequence of characters -
_matches a single character
6. List Matching with IN
When you need to match against multiple values :
|
0 1 2 3 4 5 6 7 8 |
<span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> category<span class="token punctuation">,</span> price <span class="token keyword">FROM</span> products <span class="token keyword">WHERE</span> category <span class="token operator">IN</span> <span class="token punctuation">(</span><span class="token string">'Electronics'</span><span class="token punctuation">,</span> <span class="token string">'Appliances'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Result:
| name | category | price |
|---|---|---|
| Laptop | Electronics | 999.99 |
| Coffee Maker | Appliances | 79.99 |
| Mouse | Electronics | 29.99 |
| Blender | Appliances | 129.99 |
7. Handling NULL Values
NULL represents missing or unknown data. You can’t use = with NULL – you need special operators :
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="token comment">-- Let's add a product with NULL price</span> <span class="token keyword">INSERT</span> <span class="token keyword">INTO</span> products <span class="token punctuation">(</span>name<span class="token punctuation">,</span> category<span class="token punctuation">,</span> price<span class="token punctuation">,</span> in_stock<span class="token punctuation">,</span> created_date<span class="token punctuation">)</span> <span class="token keyword">VALUES</span> <span class="token punctuation">(</span><span class="token string">'Sample Product'</span><span class="token punctuation">,</span> <span class="token string">'Misc'</span><span class="token punctuation">,</span> <span class="token boolean">NULL</span><span class="token punctuation">,</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token string">'2024-03-15'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">-- Find products with missing prices</span> <span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> price <span class="token keyword">FROM</span> products <span class="token keyword">WHERE</span> price <span class="token operator">IS</span> <span class="token boolean">NULL</span><span class="token punctuation">;</span> |
Result:
| name | price |
|---|---|
| Sample Product | NULL |
Note: Use IS NULL or IS NOT NULL, never = NULL.
Part 4: Removing Duplicates with DISTINCT
Sometimes you only want to know the unique values in a column :
|
0 1 2 3 4 5 6 7 8 |
<span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> category <span class="token keyword">FROM</span> products <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> category<span class="token punctuation">;</span> |
Result:
| category |
|---|
| Appliances |
| Electronics |
| Furniture |
| Misc |
| Office Supplies |
The DISTINCT keyword removes duplicate rows from your result set. For multiple columns, it considers the combination of all columns:
|
0 1 2 3 4 5 6 7 8 |
<span class="token keyword">SELECT</span> <span class="token keyword">DISTINCT</span> category<span class="token punctuation">,</span> in_stock <span class="token keyword">FROM</span> products <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> category<span class="token punctuation">,</span> in_stock<span class="token punctuation">;</span> |
Part 5: Sorting Results with ORDER BY
Data often comes back in unpredictable order. ORDER BY lets you control the sorting :
1. Ascending Order (Default)
|
0 1 2 3 4 5 6 7 8 |
<span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> price <span class="token keyword">FROM</span> products <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> price<span class="token punctuation">;</span> |
Result (ascending by price):
| name | price |
|---|---|
| Paper Clips | 2.50 |
| Notebook | 4.99 |
| Mouse | 29.99 |
| Desk Lamp | 45.00 |
| Coffee Maker | 79.99 |
| Blender | 129.99 |
| Desk Chair | 249.50 |
| Laptop | 999.99 |
2. Descending Order
|
0 1 2 3 4 5 6 7 8 9 |
<span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> price <span class="token keyword">FROM</span> products <span class="token keyword">WHERE</span> in_stock <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> price <span class="token keyword">DESC</span><span class="token punctuation">;</span> |
Result (descending by price):
| name | price |
|---|---|
| Laptop | 999.99 |
| Desk Chair | 249.50 |
| Blender | 129.99 |
| Coffee Maker | 79.99 |
| Desk Lamp | 45.00 |
| Mouse | 29.99 |
| Notebook | 4.99 |
| Paper Clips | 2.50 |
3. Multiple Sort Columns
|
0 1 2 3 4 5 6 7 8 |
<span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> category<span class="token punctuation">,</span> price <span class="token keyword">FROM</span> products <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> category <span class="token keyword">ASC</span><span class="token punctuation">,</span> price <span class="token keyword">DESC</span><span class="token punctuation">;</span> |
This sorts first by category (alphabetically), then within each category by price (highest first):
| name | category | price |
|---|---|---|
| Blender | Appliances | 129.99 |
| Coffee Maker | Appliances | 79.99 |
| Laptop | Electronics | 999.99 |
| Mouse | Electronics | 29.99 |
| Desk Chair | Furniture | 249.50 |
| Desk Lamp | Furniture | 45.00 |
| Sample Product | Misc | NULL |
| Notebook | Office Supplies | 4.99 |
| Paper Clips | Office Supplies | 2.50 |
Part 6: Limiting Results with LIMIT and OFFSET
When working with large tables, you often want only a subset of rows :
1. Get Top N Records
|
0 1 2 3 4 5 6 7 8 9 10 11 |
<span class="token comment">-- Get the 3 most expensive products</span> <span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> price <span class="token keyword">FROM</span> products <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> price <span class="token keyword">DESC</span> <span class="token keyword">LIMIT</span> <span class="token number">3</span><span class="token punctuation">;</span> |
Result:
| name | price |
|---|---|
| Laptop | 999.99 |
| Desk Chair | 249.50 |
| Blender | 129.99 |
2. Pagination with OFFSET
Use OFFSET to skip a certain number of rows :
|
0 1 2 3 4 5 6 7 8 9 10 11 |
<span class="token comment">-- Get products 4-6 (second page of results with 3 per page)</span> <span class="token keyword">SELECT</span> name<span class="token punctuation">,</span> price <span class="token keyword">FROM</span> products <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> price <span class="token keyword">DESC</span> <span class="token keyword">LIMIT</span> <span class="token number">3</span> <span class="token keyword">OFFSET</span> <span class="token number">3</span><span class="token punctuation">;</span> |
Result:
| name | price |
|---|---|
| Coffee Maker | 79.99 |
| Desk Lamp | 45.00 |
| Mouse | 29.99 |
This is perfect for implementing pagination in applications!
Part 7: Grouping and Aggregation
Sometimes you need summary statistics rather than individual rows :
1. Basic Aggregation Functions
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="token keyword">SELECT</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> total_products<span class="token punctuation">,</span> <span class="token function">AVG</span><span class="token punctuation">(</span>price<span class="token punctuation">)</span> <span class="token keyword">AS</span> average_price<span class="token punctuation">,</span> <span class="token function">MAX</span><span class="token punctuation">(</span>price<span class="token punctuation">)</span> <span class="token keyword">AS</span> highest_price<span class="token punctuation">,</span> <span class="token function">MIN</span><span class="token punctuation">(</span>price<span class="token punctuation">)</span> <span class="token keyword">AS</span> lowest_price<span class="token punctuation">,</span> <span class="token function">SUM</span><span class="token punctuation">(</span><span class="token keyword">CASE</span> <span class="token keyword">WHEN</span> in_stock <span class="token keyword">THEN</span> <span class="token number">1</span> <span class="token keyword">ELSE</span> <span class="token number">0</span> <span class="token keyword">END</span><span class="token punctuation">)</span> <span class="token keyword">AS</span> products_in_stock <span class="token keyword">FROM</span> products <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 punctuation">;</span> |
Result:
| total_products | average_price | highest_price | lowest_price | products_in_stock |
|---|---|---|---|---|
| 8 | 192.24375 | 999.99 | 2.50 | 6 |
2. Grouping with GROUP BY
To get these statistics per category :
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<span class="token keyword">SELECT</span> category<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> products_in_category<span class="token punctuation">,</span> <span class="token function">AVG</span><span class="token punctuation">(</span>price<span class="token punctuation">)</span> <span class="token keyword">AS</span> avg_price<span class="token punctuation">,</span> <span class="token function">MAX</span><span class="token punctuation">(</span>price<span class="token punctuation">)</span> <span class="token keyword">AS</span> max_price<span class="token punctuation">,</span> <span class="token function">MIN</span><span class="token punctuation">(</span>price<span class="token punctuation">)</span> <span class="token keyword">AS</span> min_price <span class="token keyword">FROM</span> products <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">GROUP</span> <span class="token keyword">BY</span> category <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> avg_price <span class="token keyword">DESC</span><span class="token punctuation">;</span> |
Result:
| category | products_in_category | avg_price | max_price | min_price |
|---|---|---|---|---|
| Electronics | 2 | 514.99 | 999.99 | 29.99 |
| Furniture | 2 | 147.25 | 249.50 | 45.00 |
| Appliances | 2 | 104.99 | 129.99 | 79.99 |
| Office Supplies | 2 | 3.745 | 4.99 | 2.50 |
3. Filtering Groups with HAVING
HAVING is like WHERE but for groups :
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<span class="token keyword">SELECT</span> category<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> products_in_category<span class="token punctuation">,</span> <span class="token function">AVG</span><span class="token punctuation">(</span>price<span class="token punctuation">)</span> <span class="token keyword">AS</span> avg_price <span class="token keyword">FROM</span> products <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">GROUP</span> <span class="token keyword">BY</span> category <span class="token keyword">HAVING</span> <span class="token function">AVG</span><span class="token punctuation">(</span>price<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">100</span> <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> avg_price <span class="token keyword">DESC</span><span class="token punctuation">;</span> |
Result:
| category | products_in_category | avg_price |
|---|---|---|
| Electronics | 2 | 514.99 |
| Furniture | 2 | 147.25 |
This shows only categories where the average price exceeds $100.
Part 8: Joining Tables – The Real Power
Real databases have multiple related tables. JOIN lets you combine them :
Let’s add a related table:
|
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 |
<span class="token comment">-- Create categories table</span> <span class="token keyword">CREATE</span> <span class="token keyword">TABLE</span> categories <span class="token punctuation">(</span> id <span class="token keyword">SERIAL</span> <span class="token keyword">PRIMARY</span> <span class="token keyword">KEY</span><span class="token punctuation">,</span> name <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 keyword">UNIQUE</span><span class="token punctuation">,</span> description <span class="token keyword">TEXT</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">INSERT</span> <span class="token keyword">INTO</span> categories <span class="token punctuation">(</span>name<span class="token punctuation">,</span> description<span class="token punctuation">)</span> <span class="token keyword">VALUES</span> <span class="token punctuation">(</span><span class="token string">'Electronics'</span><span class="token punctuation">,</span> <span class="token string">'Gadgets and electronic devices'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Furniture'</span><span class="token punctuation">,</span> <span class="token string">'Items for furnishing your space'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Appliances'</span><span class="token punctuation">,</span> <span class="token string">'Home and kitchen appliances'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token string">'Office Supplies'</span><span class="token punctuation">,</span> <span class="token string">'Everyday items for the office'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">-- Add category_id to products (we'll update it)</span> <span class="token keyword">ALTER</span> <span class="token keyword">TABLE</span> products <span class="token keyword">ADD</span> <span class="token keyword">COLUMN</span> category_id <span class="token keyword">INTEGER</span><span class="token punctuation">;</span> <span class="token keyword">UPDATE</span> products <span class="token keyword">SET</span> category_id <span class="token operator">=</span> <span class="token keyword">CASE</span> category <span class="token keyword">WHEN</span> <span class="token string">'Electronics'</span> <span class="token keyword">THEN</span> <span class="token number">1</span> <span class="token keyword">WHEN</span> <span class="token string">'Furniture'</span> <span class="token keyword">THEN</span> <span class="token number">2</span> <span class="token keyword">WHEN</span> <span class="token string">'Appliances'</span> <span class="token keyword">THEN</span> <span class="token number">3</span> <span class="token keyword">WHEN</span> <span class="token string">'Office Supplies'</span> <span class="token keyword">THEN</span> <span class="token number">4</span> <span class="token keyword">END</span><span class="token punctuation">;</span> |
INNER JOIN – Only Matching Rows
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<span class="token keyword">SELECT</span> p<span class="token punctuation">.</span>name <span class="token keyword">AS</span> product_name<span class="token punctuation">,</span> p<span class="token punctuation">.</span>price<span class="token punctuation">,</span> c<span class="token punctuation">.</span>name <span class="token keyword">AS</span> category_name<span class="token punctuation">,</span> c<span class="token punctuation">.</span>description <span class="token keyword">FROM</span> products p <span class="token keyword">INNER</span> <span class="token keyword">JOIN</span> categories c <span class="token keyword">ON</span> p<span class="token punctuation">.</span>category_id <span class="token operator">=</span> c<span class="token punctuation">.</span>id <span class="token keyword">WHERE</span> p<span class="token punctuation">.</span>price <span class="token operator">></span> <span class="token number">50</span> <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> p<span class="token punctuation">.</span>price <span class="token keyword">DESC</span><span class="token punctuation">;</span> |
Result:
| product_name | price | category_name | description |
|---|---|---|---|
| Laptop | 999.99 | Electronics | Gadgets and electronic devices |
| Desk Chair | 249.50 | Furniture | Items for furnishing your space |
| Blender | 129.99 | Appliances | Home and kitchen appliances |
| Coffee Maker | 79.99 | Appliances | Home and kitchen appliances |
This combines product information with category details.
Part 9: Putting It All Together – Real-World Examples
Let’s see how these pieces work together in practical scenarios:
Example 1: Product Catalog with Pagination
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<span class="token keyword">SELECT</span> p<span class="token punctuation">.</span>id<span class="token punctuation">,</span> p<span class="token punctuation">.</span>name<span class="token punctuation">,</span> p<span class="token punctuation">.</span>price<span class="token punctuation">,</span> c<span class="token punctuation">.</span>name <span class="token keyword">AS</span> category<span class="token punctuation">,</span> <span class="token keyword">CASE</span> <span class="token keyword">WHEN</span> p<span class="token punctuation">.</span>in_stock <span class="token keyword">THEN</span> <span class="token string">'In Stock'</span> <span class="token keyword">ELSE</span> <span class="token string">'Out of Stock'</span> <span class="token keyword">END</span> <span class="token keyword">AS</span> availability <span class="token keyword">FROM</span> products p <span class="token keyword">JOIN</span> categories c <span class="token keyword">ON</span> p<span class="token punctuation">.</span>category_id <span class="token operator">=</span> c<span class="token punctuation">.</span>id <span class="token keyword">WHERE</span> p<span class="token punctuation">.</span>price <span class="token operator">BETWEEN</span> <span class="token number">10</span> <span class="token operator">AND</span> <span class="token number">500</span> <span class="token operator">AND</span> c<span class="token punctuation">.</span>name <span class="token operator">IN</span> <span class="token punctuation">(</span><span class="token string">'Electronics'</span><span class="token punctuation">,</span> <span class="token string">'Furniture'</span><span class="token punctuation">)</span> <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> c<span class="token punctuation">.</span>name<span class="token punctuation">,</span> p<span class="token punctuation">.</span>price <span class="token keyword">DESC</span> <span class="token keyword">LIMIT</span> <span class="token number">5</span> <span class="token keyword">OFFSET</span> <span class="token number">0</span><span class="token punctuation">;</span> |
Example 2: Sales Dashboard Summary
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span class="token keyword">SELECT</span> EXTRACT<span class="token punctuation">(</span><span class="token keyword">YEAR</span> <span class="token keyword">FROM</span> created_date<span class="token punctuation">)</span> <span class="token keyword">AS</span> <span class="token keyword">year</span><span class="token punctuation">,</span> EXTRACT<span class="token punctuation">(</span><span class="token keyword">MONTH</span> <span class="token keyword">FROM</span> created_date<span class="token punctuation">)</span> <span class="token keyword">AS</span> <span class="token keyword">month</span><span class="token punctuation">,</span> c<span class="token punctuation">.</span>name <span class="token keyword">AS</span> category<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> products_added<span class="token punctuation">,</span> <span class="token function">ROUND</span><span class="token punctuation">(</span><span class="token function">AVG</span><span class="token punctuation">(</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_price<span class="token punctuation">,</span> <span class="token function">ROUND</span><span class="token punctuation">(</span><span class="token function">SUM</span><span class="token punctuation">(</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> total_value <span class="token keyword">FROM</span> products p <span class="token keyword">JOIN</span> categories c <span class="token keyword">ON</span> p<span class="token punctuation">.</span>category_id <span class="token operator">=</span> c<span class="token punctuation">.</span>id <span class="token keyword">GROUP</span> <span class="token keyword">BY</span> <span class="token keyword">year</span><span class="token punctuation">,</span> <span class="token keyword">month</span><span class="token punctuation">,</span> c<span class="token punctuation">.</span>name <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> <span class="token keyword">year</span> <span class="token keyword">DESC</span><span class="token punctuation">,</span> <span class="token keyword">month</span> <span class="token keyword">DESC</span><span class="token punctuation">,</span> total_value <span class="token keyword">DESC</span><span class="token punctuation">;</span> |
Example 3: Inventory Check
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span class="token keyword">SELECT</span> c<span class="token punctuation">.</span>name <span class="token keyword">AS</span> category<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> total_products<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">CASE</span> <span class="token keyword">WHEN</span> p<span class="token punctuation">.</span>in_stock <span class="token keyword">THEN</span> <span class="token number">1</span> <span class="token keyword">END</span><span class="token punctuation">)</span> <span class="token keyword">AS</span> in_stock<span class="token punctuation">,</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">CASE</span> <span class="token keyword">WHEN</span> <span class="token operator">NOT</span> p<span class="token punctuation">.</span>in_stock <span class="token keyword">THEN</span> <span class="token number">1</span> <span class="token keyword">END</span><span class="token punctuation">)</span> <span class="token keyword">AS</span> out_of_stock<span class="token punctuation">,</span> <span class="token function">ROUND</span><span class="token punctuation">(</span><span class="token number">100.0</span> <span class="token operator">*</span> <span class="token function">COUNT</span><span class="token punctuation">(</span><span class="token keyword">CASE</span> <span class="token keyword">WHEN</span> p<span class="token punctuation">.</span>in_stock <span class="token keyword">THEN</span> <span class="token number">1</span> <span class="token keyword">END</span><span class="token punctuation">)</span> <span class="token operator">/</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 punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">AS</span> in_stock_percentage <span class="token keyword">FROM</span> products p <span class="token keyword">JOIN</span> categories c <span class="token keyword">ON</span> p<span class="token punctuation">.</span>category_id <span class="token operator">=</span> c<span class="token punctuation">.</span>id <span class="token keyword">GROUP</span> <span class="token keyword">BY</span> c<span class="token punctuation">.</span>name <span class="token keyword">HAVING</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 operator">></span> <span class="token number">1</span> <span class="token keyword">ORDER</span> <span class="token keyword">BY</span> in_stock_percentage <span class="token keyword">DESC</span><span class="token punctuation">;</span> |
Part 10: Best Practices and Performance Tips
DO:
-
Specify columns explicitly – Never use
SELECT *in production -
Use meaningful aliases – Make your results readable
0123456<span class="token keyword">SELECT</span> p<span class="token punctuation">.</span>name <span class="token keyword">AS</span> product_name<span class="token punctuation">,</span> c<span class="token punctuation">.</span>name <span class="token keyword">AS</span> category_name -
Filter early – Use
WHEREto reduce data before joins and aggregations -
Index columns used in WHERE, JOIN, and ORDER BY – Dramatically improves performance
-
Use appropriate data types – Don’t store numbers as text
DON’T:
-
Don’t use
SELECT DISTINCTas a crutch – It often hides poor query design -
Don’t overuse subqueries – Sometimes joins are more efficient
-
Don’t forget NULL handling – NULLs behave unexpectedly in comparisons
-
Don’t assume sort order – Always use
ORDER BYif order matters
Understanding Query Execution Order
It’s crucial to understand that SQL is written in one order but executed in another:
-
FROM (including JOINs) – Identify tables
-
WHERE – Filter rows
-
GROUP BY – Form groups
-
HAVING – Filter groups
-
SELECT – Choose columns and calculate expressions
-
ORDER BY – Sort results
-
LIMIT/OFFSET – Limit output
This explains why you can’t use column aliases from SELECT in WHERE – the alias doesn’t exist yet when WHERE is evaluated!
Summary: The SELECT Statement Philosophy
The SELECT statement is your primary tool for conversation with your database. It’s how you ask questions and get answers. Master these concepts in order:
-
Simple Selection – Get specific columns
-
Filtering – Narrow down to relevant rows
-
Sorting – Organize results meaningfully
-
Aggregation – Summarize and analyze
-
Joining – Connect related data
-
Combining – Use all features together
Every great SQL query starts with understanding what question you’re asking your data. The SELECT statement is simply the grammar you use to phrase that question precisely.
Remember: The database will give you exactly what you ask for – no more, no less. Learning to ask the right way is the art and science of working with PostgreSQL.
Would you like me to elaborate on any specific aspect of SELECT queries, such as more advanced join types, subqueries, window functions, or performance optimization?
