Skip to main content

SELECT Queries

The SELECT statement is the foundation of Data Query Language (DQL) in SQL. It is used to retrieve data from one or more tables in a relational database. SELECT is declarative — we describe what data we want to fetch, not how to fetch it.

Every database user, from beginner to expert, uses SELECT more than any other SQL command. It is essential for data exploration, reporting, and building applications.

Basic Syntax

SELECT column_list
FROM table_name
[WHERE condition]
[ORDER BY column_name [ASC|DESC]]
[LIMIT n / FETCH FIRST n ROWS ONLY];

Explanation:

  • SELECT – specifies which columns to retrieve.
  • FROM – specifies the table to query data from.
  • WHERE – filters rows based on conditions.
  • ORDER BY – sorts the result.
  • LIMIT / FETCH – restricts the number of rows returned.

Selecting All Columns

To retrieve all columns from a table:

SELECT * FROM employees;

The * wildcard fetches every column from the table. While convenient, it’s not recommended in production queries because it can:

  • Retrieve unnecessary data,
  • Increase network load,
  • Break when schemas change.

Selecting Specific Columns

To fetch only certain columns:

SELECT name, department FROM employees;

This returns only the name and department columns.

Using Column Aliases

Aliases rename columns in the output (useful for readability or derived expressions).

SELECT name AS employee_name, department AS dept FROM employees;

The AS keyword is optional:

SELECT name employee_name, department dept FROM employees;

Renaming Tables with Aliases

Table aliases are used for convenience or to disambiguate tables in larger queries:

SELECT e.name, e.salary FROM employees AS e;

Filtering Rows with WHERE

The WHERE clause restricts rows that appear in the result set.

SELECT * FROM employees WHERE department = 'Sales';

Common operators:

OperatorDescriptionExample
=Equal tosalary = 50000
!= or <>Not equal todepartment <> 'HR'
> / <Greater/Less thansalary > 60000
>= / <=Greater/Less than or equalsalary >= 45000
BETWEENWithin rangesalary BETWEEN 40000 AND 60000
INMatch any in a listdepartment IN ('HR', 'IT')
LIKEPattern matchname LIKE 'A%'
IS NULLCheck for null valuesmanager_id IS NULL

Sorting Results

We can sort the results using ORDER BY.

SELECT name, salary FROM employees ORDER BY salary DESC;
  • ASC – ascending order (default)
  • DESC – descending order

Sorting by multiple columns:

SELECT name, department, salary
FROM employees
ORDER BY department ASC, salary DESC;

Limiting the Number of Rows

Different databases provide different ways to limit results.

DatabaseSyntax Example
MySQL / PostgreSQL / SQLiteSELECT * FROM employees LIMIT 10;
SQL ServerSELECT TOP 10 * FROM employees;
Oracle (12c+)SELECT * FROM employees FETCH FIRST 10 ROWS ONLY;
Older Oracle versionsSELECT * FROM (SELECT * FROM employees) WHERE ROWNUM <= 10;

Removing Duplicates with DISTINCT

DISTINCT eliminates duplicate rows in the output.

SELECT DISTINCT department FROM employees;

It applies to the entire row (all selected columns), not just one column.

Using Expressions in SELECT

We can compute new columns using expressions:

SELECT name, salary * 1.1 AS new_salary FROM employees;

Here, each employee’s salary is increased by 10% and displayed as new_salary.

Expressions can use:

  • Arithmetic operators (+, -, *, /)
  • String concatenation
  • Conditional expressions like CASE

Example:

SELECT name,
CASE WHEN salary > 80000 THEN 'High'
WHEN salary > 50000 THEN 'Medium'
ELSE 'Low' END AS salary_level
FROM employees;

Using SQL Functions (Non-Aggregate)

Even without aggregation, SQL provides scalar functions that operate on individual values:

Function TypeExampleDescription
StringUPPER(name)Converts to uppercase
DateCURRENT_DATEReturns current date
NumericROUND(salary, 2)Rounds to 2 decimal places
ConditionalCOALESCE(bonus, 0)Replaces NULL with 0

Example:

SELECT id, UPPER(name) AS name_caps, COALESCE(manager_id, 0) AS mgr
FROM employees;

SQL SELECT Differences Across Databases

Although SQL is standardized (ANSI SQL), databases have subtle differences in syntax, functions, and features.

FeatureMySQLPostgreSQLSQLiteSQL ServerOracle
Limit resultsLIMIT 10LIMIT 10LIMIT 10TOP 10FETCH FIRST 10 ROWS ONLY
Current dateCURDATE()CURRENT_DATEdate('now')GETDATE()SYSDATE
Case sensitivityCase-insensitive by defaultCase-sensitiveCase-insensitiveCase-insensitiveCase-insensitive
Aliases with ASOptionalOptionalOptionalOptionalOptional
Conditional functionIF(condition, a, b)CASE WHEN ...CASE WHEN ...IIF(condition, a, b)CASE WHEN ...
Limit + OffsetLIMIT 10 OFFSET 5LIMIT 10 OFFSET 5LIMIT 10 OFFSET 5OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLYOFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY

These differences are minor for basic SELECT queries but become more important when using advanced SQL features like window functions, CTEs, or JSON handling.

Execution Order of a SELECT Query

Though we write SQL in a specific order, the logical execution order inside the database is different:

ClauseLogical OrderDescription
FROM1Identify tables and joins
WHERE2Filter rows
SELECT3Choose columns and expressions
DISTINCT4Remove duplicates
ORDER BY5Sort the result
LIMIT/FETCH6Restrict output rows

So this query:

SELECT name FROM employees WHERE department = 'IT' ORDER BY name LIMIT 5;

is logically processed in the above order.