Part II: Retrieving Data
Chapter 3: Basic SELECT Queries
Retrieving data is the core skill every SQL user must master. Whether you’re exploring a new dataset, debugging an application, or building reports, the SELECT statement is your primary tool. In this chapter, we’ll explore:
The anatomy of a
SELECTstatementHow to choose specific columns and rename them with aliases
Filtering rows precisely with the
WHEREclauseSorting results using
ORDER BYLimiting output for faster testing with
LIMITandTOP
By the end, you’ll have the confidence to write queries that fetch exactly the data you need—no more, no less.
1. Anatomy of the SELECT Statement
Every SQL query starts with the SELECT clause, which defines what you want to see, and the FROM clause, which specifies where that data lives. A simple query looks like this:
SELECT column1, column2
FROM table_name;
Here’s the typical order of clauses in a SELECT statement:
SELECT – List of columns or expressions to return.
FROM – One or more tables or subqueries.
WHERE – Filters rows before they reach the output.
GROUP BY – Groups rows for aggregation (covered in Chapter 5).
HAVING – Filters groups after aggregation (Chapter 5).
ORDER BY – Sorts the final result set.
LIMIT / TOP – Restricts the number of rows returned.
Even if you omit optional parts like WHERE or ORDER BY, SQL internally processes the clauses in the order above. Understanding this logical flow helps you debug unexpected results.
2. Choosing Columns and Renaming with Aliases
2.1 Explicit Column Lists vs. SELECT *
Using SELECT * returns every column in the table:
SELECT *
FROM employees;
Drawbacks of SELECT *:
Transfers unnecessary data over the network
Breaks if new columns are added or column order changes
Makes intent unclear to readers
Instead, list only the columns you need:
SELECT first_name, last_name, hire_date
FROM employees;
This approach:
Improves performance by reducing I/O
Clarifies which data matters
Guards against schema changes
2.2 Column Aliases
Aliases let you rename columns or expressions in your result set for readability:
SELECT
employee_id AS id,
first_name || ' ' || last_name AS full_name,
salary * 1.10 AS adjusted_salary
FROM employees;
AS idsimplifiesemployee_id.Concatenating first and last names gives
full_name.Applying a 10% raise yields
adjusted_salary.
Aliases are especially helpful when you apply functions or calculations. Always choose descriptive alias names that reflect the data.
3. Filtering Rows Using WHERE
The WHERE clause narrows down which rows appear in your output. You can use comparison, pattern matching, and logical operators to construct precise filters.
3.1 Comparison Operators
SELECT order_id, total_amount
FROM orders
WHERE total_amount > 100.00
AND status = 'completed';
Common operators:
=,<>(not equal)<,>,<=,>=BETWEEN … AND …(inclusive range)IN (…)(set membership)
3.2 Pattern Matching with LIKE
Search strings with % (any sequence) and _ (single character):
SELECT email
FROM customers
WHERE email LIKE '%@gmail.com';
This returns all Gmail addresses. Use ILIKE in PostgreSQL for case-insensitive matching.
3.3 Handling NULL Values
NULL represents missing or unknown data. Comparisons require IS NULL or IS NOT NULL:
SELECT *
FROM employees
WHERE manager_id IS NOT NULL;
Avoid = NULL—it always yields false.
3.4 Combining Conditions
Use AND, OR, and parentheses to build complex filters:
SELECT *
FROM orders
WHERE (status = 'shipped' OR status = 'delivered')
AND order_date BETWEEN '2025-01-01' AND '2025-06-30';
Parentheses group conditions so that OR is evaluated before AND.
4. Sorting Results with ORDER BY
The default order of rows in a result set is undefined. To impose a meaningful sequence, use ORDER BY:
SELECT order_id, order_date, total_amount
FROM orders
ORDER BY order_date DESC, total_amount ASC;
DESCsorts in descending order (newest first).ASC(default) sorts ascending.You can sort by column position (
ORDER BY 2 DESC) but explicit names improve clarity.
Performance tip: Index the columns you sort by to speed up large result sets.
5. Limiting Output for Faster Testing
During development, you often don’t need the full result set. Limiting output speeds up query execution and reduces network load.
| Database | Syntax | Example |
|---|---|---|
| MySQL, PostgreSQL, SQLite | LIMIT <count> [OFFSET <n>] | SELECT * FROM users LIMIT 10; |
| SQL Server | SELECT TOP <count> * | SELECT TOP 10 * FROM users; |
5.1 LIMIT and OFFSET
SELECT id, name
FROM products
ORDER BY name
LIMIT 5 OFFSET 10;
Returns rows 11 through 15 after sorting by name.
5.2 TOP
SELECT TOP 5 *
FROM products
ORDER BY name;
Choose the syntax your RDBMS supports. Limiting rows is essential when exploring large tables or testing new queries.
6. Putting It All Together: Practical Examples
Example A: Top 5 High-Value Customers
SELECT
c.customer_id AS id,
c.first_name || ' ' || c.last_name AS customer,
SUM(o.total_amount) AS lifetime_spend
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, customer
ORDER BY lifetime_spend DESC
LIMIT 5;
This query finds the top five customers by total spend.
Example B: Recent Low-Stock Products
SELECT
p.product_id,
p.product_name,
i.stock_level
FROM products p
JOIN inventory i ON p.product_id = i.product_id
WHERE i.stock_level < 20
ORDER BY i.stock_level ASC;
Lists products running low on stock, sorted by urgency.
7. Best Practices and Tips
Specify columns: Avoid
SELECT *to improve performance and clarity.Use aliases: Make your result sets easier to read and maintain.
Filter early: Push conditions into
WHEREto reduce data processed.Index sorting columns: Speed up
ORDER BYon large tables.Limit during development: Use
LIMIT/TOPto iterate quickly.Test your filters: Preview row counts with
SELECT COUNT(*)before fetching full data.
By mastering these basic SELECT techniques—choosing the right columns, filtering precisely, sorting intentionally, and limiting output—you’ll build a strong foundation for all subsequent SQL skills. In Chapter 4, we’ll dive deeper into advanced filtering and expressions to handle even more complex querying scenarios.

Comments
Post a Comment