SELECT statement. This page walks you through every major SELECT feature, from the simplest column retrieval to grouped aggregations with HAVING, using a consistent employees database throughout.
The Sample Data
All examples use these two tables. Set them up using the SQLite Setup page if you have not already. employee (selected rows shown)SELECT — Retrieve Columns
SELECT tells SQL which columns to return. FROM tells it which table to read.
All Columns
* is a wildcard meaning “every column”. Use it for quick exploration, but name columns explicitly in production code so schema changes do not silently break your queries.
Specific Columns
Column Aliases with AS
Give a column a temporary display name usingAS. Aliases make output readable and are required when you rename calculated expressions.
You cannot use an alias defined in
SELECT inside a WHERE clause. SQL executes WHERE before SELECT, so the alias does not yet exist at that point. Use the original expression or a subquery instead.DISTINCT — Remove Duplicates
DISTINCT eliminates duplicate values from the result.
WHERE — Filter Rows
WHERE evaluates a condition for each row and includes only the rows where the condition is TRUE.
Comparison Operators
Logical Operators: AND, OR, NOT
Combine multiple conditions with logical operators.BETWEEN — Range Check
BETWEEN is inclusive — both boundary values are included.
IN — List Membership
IN is cleaner and often faster when matching against a list of values.
LIKE — Pattern Matching
LIKE searches text columns for patterns. Two wildcards are available:
IS NULL / IS NOT NULL
NULL means “unknown value”. You cannot test for NULL using =; you must use IS NULL.
Practice: Filter employees
Write a query that returns the name and salary of employees from Hyderabad who earn more than ₹55,000.Solution
Solution
ORDER BY — Sort Results
ORDER BY sorts the result set. Default order is ascending (ASC). Use DESC for descending.
LIMIT and OFFSET — Pagination
LIMIT caps the number of rows returned. OFFSET skips a given number of rows before starting to return results. Together they power pagination.
Aggregate Functions
Aggregate functions collapse many rows into a single value. They are most useful when combined withGROUP BY.
Practice: Salary statistics
Write a query that returns the average, minimum, and maximum salary for all employees in one result row.Solution
Solution
GROUP BY — Aggregate Per Group
GROUP BY splits the rows into groups and applies aggregate functions to each group independently.
Every column in the
SELECT clause must either be listed in GROUP BY or wrapped in an aggregate function. You cannot select a non-grouped, non-aggregated column.HAVING — Filter Groups
WHERE filters individual rows before grouping. HAVING filters groups after aggregation. Use HAVING whenever your filter condition involves an aggregate function.
WHERE vs. HAVING — Quick Rule
SQL Execution Order
You write SQL in one order, but the database runs each clause in a different sequence. Understanding this explains many confusing behaviours (like why you cannot useSELECT aliases in WHERE).
Full Query Example
This query uses every clause covered on this page. Read it clause by clause following the execution order above.Practice: Departmental payroll report
Write a query that returns, for each department (excludingNULL), the department ID, the number of employees, and the total payroll — but only for departments whose total payroll exceeds ₹100,000. Sort by total payroll descending.
Solution
Solution
Next: SQL JOINs
Learn how to combine rows from multiple tables using INNER JOIN, LEFT JOIN, and more to answer cross-table questions.