Skip to main content
Once you master SELECT, WHERE, and JOIN, you can answer simple questions. This page gives you the tools to answer hard questions — “Who are the top 3 earners in each department?”, “What is the running total of salaries?”, “Which employees earn above the company average?” — using subqueries, CTEs, and window functions. You will also learn how indexes make queries fast and how views let you save complex queries as reusable objects.

Subqueries

A subquery is a SELECT inside another SQL statement. The inner query runs first and its result is used by the outer query. You can place subqueries in the WHERE clause, the FROM clause, or even the SELECT list.

Subquery in WHERE

The inner query computes a single value (AVG(salary)). The outer query compares each row’s salary against it.

Subquery with IN

Correlated Subquery

A correlated subquery references a column from the outer query. It re-executes for every row the outer query processes.
Correlated subqueries are powerful but can be slow on large tables because they run once per row. A JOIN or window function often achieves the same result more efficiently.

Common Table Expressions (CTEs)

A CTE gives a subquery a name and makes it readable. You define it with WITH before the main query. CTEs can reference each other, making multi-step logic clean and debuggable.

Basic CTE Syntax

Example: High Earners per Department

Chained CTEs

Use CTEs instead of deeply nested subqueries. Each CTE acts like a named, temporary result set — read the query top-to-bottom rather than inside-out.

Window Functions

Window functions perform calculations across a set of related rows without collapsing them the way GROUP BY does. Every row stays in the output; the function just adds an extra computed column. The key syntax element is OVER(...), which defines the “window” — which rows the function looks at when computing each result.

ROW_NUMBER()

Assigns a unique sequential integer to each row within a window.

Top 3 Earners Per Department

Wrap the window function in a CTE and filter on the rank:

RANK() and DENSE_RANK()

Both assign ranks but handle ties differently.
If two employees share a salary: RANK() would give them both rank 3 and skip rank 4. DENSE_RANK() gives them both rank 3 and continues with rank 4 for the next employee.

LAG() and LEAD()

Access the value from a previous (LAG) or following (LEAD) row within the window.

Running Total (Cumulative SUM)

CASE WHEN Expressions

CASE WHEN is SQL’s conditional logic — like if/elif/else inside a query.

Simple Classification

Conditional Aggregation

You can combine CASE WHEN with aggregate functions to create pivot-like summaries.

String Functions

SQLite provides built-in string functions for cleaning and transforming text data.

Date Functions

Store dates as TEXT in 'YYYY-MM-DD' format and use SQLite’s date functions to manipulate them.

Indexes

An index is a data structure that lets the database find rows matching a condition without scanning every row in the table. Think of it as the index at the back of a book.

Why Indexes Matter

Without an index, a query like WHERE city = 'Hyderabad' reads every single row (a full table scan). With an index on city, the database jumps directly to the matching rows.

When to Index

Good candidates

  • Columns used frequently in WHERE clauses
  • Columns used in JOIN conditions
  • Columns used in ORDER BY on large tables
  • Foreign key columns

When to avoid

  • Very small tables (full scan is fast enough)
  • Columns you update very frequently (indexes slow down writes)
  • Columns with very low cardinality (e.g., a boolean column)

Query Plan

Check how SQLite executes your query with EXPLAIN QUERY PLAN:
Look for USING INDEX in the output — that confirms the index is being used.

Views

A view is a saved query stored in the database that you can query like a table. It does not store data itself — it re-runs the underlying query each time you select from it.

Create a View

Query a View

Drop a View

Views are perfect for hiding complex JOINs and CASE logic from application code. Your Python script can run SELECT * FROM v_employee_details without knowing anything about the underlying table structure.

Complete Analytics Example

This query uses CTEs, window functions, and CASE expressions to produce a department-level performance report in one statement:

Next: NumPy

Move into data analysis — learn NumPy arrays, vectorized operations, and broadcasting for fast numerical computing in Python.