Introduction to SQL for Data Analytics
Why SQL is essential
Most analytics work happens where the data lives:
- Relational databases (PostgreSQL, MySQL, SQLite)
- Data warehouses (BigQuery, Snowflake, Redshift)
SQL is used to:
- Retrieve data efficiently
- Aggregate metrics (DAU, revenue, churn)
- Join multiple tables (users + orders + events)
Core mental model
- Data is stored in tables.
- A query reads rows/columns and returns a result set.
SELECT *
FROM users
LIMIT 10;SELECT *
FROM users
LIMIT 10;Typical analytics tables
users(user_id, created_at, country, plan)users(user_id, created_at, country, plan)orders(order_id, user_id, order_ts, amount)orders(order_id, user_id, order_ts, amount)events(user_id, event_ts, event_name, device)events(user_id, event_ts, event_name, device)
What you’ll learn in this phase
SELECTSELECT,WHEREWHERE,ORDER BYORDER BY,LIMITLIMIT- Aggregations:
COUNTCOUNT,SUMSUM,AVGAVG GROUP BYGROUP BY,HAVINGHAVING- Joins
- Window functions
- CTEs
- Using SQL from Python (pandas)
Where SQL fits in an analytics workflow
You rarely run one query in isolation. The usual shape of the work is: raw tables live in a database, a query filters and reshapes them, and the result lands somewhere you can chart, model, or share.
flowchart LR A["users table"] --> D["SQL query"] B["orders table"] --> D C["events table"] --> D D --> E["Result set (rows + columns)"] E --> F["pandas DataFrame / BI dashboard"]
The database never changes because you queried it — a SELECTSELECT just reads and returns rows.
That’s what makes SQL safe to explore with: you can run the same query a hundred times while
you’re figuring out the right filter, and nothing gets damaged.
SQLite: a database in a single file
You don’t need a server to practice SQL. SQLite (Python’s built-in sqlite3sqlite3 module) stores an
entire database in one file — or even in memory — which makes it perfect for learning and for
the exercises on this page.
import sqlite3
conn = sqlite3.connect(":memory:")
conn.execute("CREATE TABLE users (user_id INTEGER, country TEXT, plan TEXT)")
conn.executemany(
"INSERT INTO users VALUES (?, ?, ?)",
[(1, "IN", "free"), (2, "IN", "pro"), (3, "US", "pro")],
)
conn.commit()
rows = conn.execute("SELECT * FROM users").fetchall()
print(rows)import sqlite3
conn = sqlite3.connect(":memory:")
conn.execute("CREATE TABLE users (user_id INTEGER, country TEXT, plan TEXT)")
conn.executemany(
"INSERT INTO users VALUES (?, ?, ?)",
[(1, "IN", "free"), (2, "IN", "pro"), (3, "US", "pro")],
)
conn.commit()
rows = conn.execute("SELECT * FROM users").fetchall()
print(rows)[(1, 'IN', 'free'), (2, 'IN', 'pro'), (3, 'US', 'pro')][(1, 'IN', 'free'), (2, 'IN', 'pro'), (3, 'US', 'pro')]🧪 Try It Yourself
Exercise 1 – Create a table and read it back
Exercise 2 – Filter rows with WHERE
Exercise 3 – Load a query result into pandas
Next
Head to SQL Basics (SELECT, WHERE, ORDER BY, LIMIT) to practice the four clauses you’ll use in almost every query you ever write.
If this helped you, consider buying me a coffee ☕
Buy me a coffeeWas this page helpful?
Let us know how we did
