Topic 17 of

SQL SELECT, WHERE, ORDER BY — Complete Beginner Guide

Three commands. That's all it takes to answer 80% of basic business questions with SQL. Let's master all three deeply enough that they become second nature.

📚Beginner
⏱️11 min
7 quizzes
🎯

SELECT — Choosing Exactly What You Need

You already know that SELECT picks columns. Let's go deeper — because there's more to it than just listing column names.

Selecting Specific Columns

Always prefer selecting only the columns you need. Never use SELECT * in production queries — it's wasteful, slows things down, and makes your query fragile if the table structure changes.

query.sqlSQL
-- Bad habit: fetches everything including irrelevant columns
SELECT * FROM customers;

-- Good habit: explicit, clear, fast
SELECT customer_id, name, city, signup_date
FROM customers;

Aliasing Columns with AS

AS renames a column in your output — useful when column names are unclear or when you're creating calculated values:

query.sqlSQL
SELECT
  order_id,
  amount,
  amount * 0.18 AS gst_amount,
  amount + (amount * 0.18) AS total_with_gst
FROM orders;

Removing Duplicates with DISTINCT

DISTINCT returns only unique values in a column:

query.sqlSQL
-- How many unique cities do we have orders from?
SELECT DISTINCT city FROM orders;

-- Unique combinations of city + restaurant
SELECT DISTINCT city, restaurant FROM orders;
Think of it this way...

DISTINCT is like asking someone to list all the states in India that have a Zomato presence — you don't want "Maharashtra" listed 4 million times just because there are 4 million orders from Maharashtra. You want the list once.

🔎

WHERE — Filtering With Precision

The WHERE clause filters rows before they're returned to you. Let's cover every operator you'll actually use.

Text Matching with LIKE

LIKE lets you match patterns in text columns using wildcards:

  • % matches zero or more characters
  • _ matches exactly one character
query.sqlSQL
-- Restaurants starting with "Burger"
SELECT * FROM orders WHERE restaurant LIKE 'Burger%';

-- Restaurants with "pizza" anywhere in the name (case-insensitive in most DBs)
SELECT * FROM orders WHERE restaurant LIKE '%pizza%';

-- Restaurant names that are exactly 6 characters
SELECT * FROM orders WHERE restaurant LIKE '______';

Date Filtering

query.sqlSQL
-- Orders from a specific date
SELECT * FROM orders WHERE order_date = '2026-01-15';

-- Orders in January 2026
SELECT * FROM orders
WHERE order_date BETWEEN '2026-01-01' AND '2026-01-31';

-- Orders in the last 7 days (varies by SQL dialect)
SELECT * FROM orders
WHERE order_date >= CURRENT_DATE - INTERVAL '7 days';  -- PostgreSQL
WHERE order_date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY); -- MySQL

Handling NULL Values

NULL requires special treatment — you can't use = with it:

query.sqlSQL
-- WRONG: this returns 0 rows even if NULLs exist
SELECT * FROM orders WHERE delivery_time = NULL;

-- RIGHT: always use IS NULL or IS NOT NULL
SELECT * FROM orders WHERE delivery_time IS NULL;
SELECT * FROM orders WHERE delivery_time IS NOT NULL;
Info

Key Takeaway: NULL = NULL is always false in SQL — NULL is never equal to anything, including itself. Always use IS NULL or IS NOT NULL to check for missing values.

⚠️ CheckpointQuiz error: Missing or invalid options array

↕️

ORDER BY — Sorting That Makes Sense

Sorting seems simple, but there are nuances that matter in real queries.

Sorting by Multiple Columns

query.sqlSQL
-- Sort by city A-Z, then by amount highest first within each city
SELECT customer_id, city, amount
FROM orders
ORDER BY city ASC, amount DESC;

Sorting by Column Position

You can reference columns by their position number in the SELECT list — useful for long queries:

query.sqlSQL
SELECT customer_id, city, amount, order_date
FROM orders
ORDER BY 4 DESC;  -- sorts by order_date (4th column)

NULL Sorting Behavior

By default, NULLs sort differently in different databases:

  • PostgreSQL/SQLite: NULLs sort last in ASC, first in DESC
  • MySQL: NULLs sort first in ASC (treated as lowest value)
query.sqlSQL
-- Force NULLs to the end regardless of sort direction (PostgreSQL)
SELECT * FROM orders ORDER BY delivery_time ASC NULLS LAST;

OFFSET for Pagination

LIMIT with OFFSET lets you page through results — useful when building reports:

query.sqlSQL
-- Show rows 11-20 (second page of 10)
SELECT order_id, amount FROM orders
ORDER BY order_date DESC
LIMIT 10 OFFSET 10;
Think of it this way...

When IRCTC shows train search results, they use ORDER BY to sort by departure time, and LIMIT/OFFSET to show 20 results per page. The query runs fresh each time you click "Next page."

🔧

Combining All Three — Real Query Examples

Let's write queries you'd actually use at work.

Business Question 1: Top 10 highest-value orders from Bangalore this month

query.sqlSQL
SELECT
  order_id,
  customer_id,
  restaurant,
  amount
FROM orders
WHERE city = 'Bangalore'
  AND order_date BETWEEN '2026-03-01' AND '2026-03-31'
ORDER BY amount DESC
LIMIT 10;

Business Question 2: Customers who haven't completed their profile

query.sqlSQL
SELECT
  customer_id,
  name,
  email,
  signup_date
FROM customers
WHERE phone IS NULL
   OR address IS NULL
ORDER BY signup_date DESC;

Business Question 3: All cancelled orders not from Delhi or Mumbai

query.sqlSQL
SELECT
  order_id,
  city,
  amount,
  cancellation_reason
FROM orders
WHERE status = 'cancelled'
  AND city NOT IN ('Delhi', 'Mumbai')
ORDER BY amount DESC;
Info

Writing tip: When debugging a query that returns unexpected results, remove clauses one at a time — first remove ORDER BY, then WHERE, then extra SELECT columns — to isolate which part is causing the issue.

⚠️ FinalQuiz error: Missing or invalid questions array

⚠️ SummarySection error: Missing or invalid items array

Received: {"hasItems":false,"isArray":false}