# How to Learn SQL for Free: A Practice-First Plan With Real Queries

> Free courses, practice sites, and sample databases to learn SQL step by step, from SELECT and JOIN to CTEs and window functions.

Source: https://www.erathos.com/en/blog/how-to-learn-sql-for-free
Em português: https://www.erathos.com/blog/how-to-learn-sql-for-free
Published: 2026-09-12
Category: Tutorials

![How Learn SQL for Fre](https://cms-media.erathos.com/How Learn SQL for Free.png)

SQL is the language you use to ask a database questions. In the [2025 Stack Overflow Developer Survey](https://survey.stackoverflow.co/2025/technology), 58.6% of all respondents said they used SQL in the past year. Only JavaScript and HTML/CSS scored higher. The good news for anyone learning it: the best material is free, the databases are free, and the practice data is free. This guide lists what we'd use, in what order, and shows the queries running on a real database.

## Can you learn SQL for free?

Yes. Free, browser-based courses like SQLBolt, Khan Academy, and Harvard's CS50 SQL cover everything from a first SELECT to window functions, and SQLite and DuckDB give you a free database on your own laptop. You pay nothing unless you want a certificate.

SQL is an open standard. The current version is [ISO/IEC 9075-1:2023](https://www.iso.org/standard/76583.html), published in June 2023. Every major database (PostgreSQL, MySQL, SQLite, SQL Server, BigQuery) follows most of that standard, so what you learn on one carries over to the others with small changes. We cover those changes in the dialect section below.

The one thing money buys is a certificate. [CS50's SQL course](https://cs50.harvard.edu/sql/) is free to take through its OpenCourseWare page, and a verified certificate comes only through edX. [Codecademy's Learn SQL](https://www.codecademy.com/learn/learn-sql) is marked Free on its course page, and the certificate of completion is in the paid tier. The lessons are the same either way.

## What order should you learn SQL in?

Learn SQL in this order: SELECT and FROM, then WHERE and ORDER BY, then GROUP BY with COUNT and SUM, then JOIN, then subqueries and CTEs, then window functions. Each step reuses the one before it, and every free course in this guide follows about the same path.

To show what that path looks like, we ran each step against the Chinook database. Chinook is a [free sample database](https://github.com/lerocha/chinook-database) that models a digital music store, with scripts for SQLite, PostgreSQL, MySQL, SQL Server, Oracle, and DB2. The SQLite file is about 1 MB. These are its tables:

Album      Customer     Genre       InvoiceLine     Playlist          Track
`Artist     Employee     Invoice     MediaType       PlaylistTrack`

Step one is picking columns from a table and limiting how many rows come back:

`SELECT Name`
`FROM Artist`
`LIMIT 5;`

`╭───────────────────╮`
`│       Name        │`
`╞═══════════════════╡`
`│ AC/DC             │`
`│ Accept            │`
`│ Aerosmith         │`
`│ Alanis Morissette │`
`│ Alice In Chains   │`
`╰───────────────────╯`

Step two filters rows with WHERE and sorts them with ORDER BY. Here we find tracks longer than ten minutes and convert milliseconds to minutes in the SELECT:

`SELECT Name, Milliseconds / 60000.0 AS minutes`
`FROM Track`
`WHERE Milliseconds > 600000`
`ORDER BY Milliseconds DESC`
`LIMIT 5;`

`╭─────────────────────────────┬────────────────────╮`
`│            Name             │      minutes       │`
`╞═════════════════════════════╪════════════════════╡`
`│ Occupation / Precipice      │ 88.115883333333329 │`
`│ Through a Looking Glass     │ 84.813966666666673 │`
`│ Greetings from Earth, Pt. 1 │ 49.338216666666668 │`
`│ The Man With Nine Lives     │            49.2833 │`
`│ Battlestar Galactica, Pt. 2 │ 49.268016666666668 │`
`╰─────────────────────────────┴────────────────────╯`

Step three groups rows and counts them. GROUP BY collapses the 59 customers into one row per country, and HAVING filters on the count after grouping:

`SELECT Country, COUNT(*) AS customer_count`
`FROM Customer`
`GROUP BY Country`
`HAVING COUNT(*) > 5`
`ORDER BY customer_count DESC;`

`╭─────────┬────────────────╮`
`│ Country │ customer_count │`
`╞═════════╪════════════════╡`
`│ USA     │             13 │`
`│ Canada  │              8 │`
`╰─────────┴────────────────╯`

The HAVING clause exists because WHERE runs before grouping. If you try to filter on the aggregate inside WHERE, SQLite stops you:

`SELECT CustomerId, SUM(Total) AS total_spent`
`FROM Invoice`
`WHERE total_spent > 20`
`GROUP BY CustomerId;`

`Parse error near line 3: misuse of aggregate: SUM()`

Step four joins two tables on a shared key. Album has an ArtistId column that points at Artist, so the join pairs each album with its artist:

`SELECT Album.Title, Artist.Name AS artist`
`FROM Album JOIN Artist`
`  ON Album.ArtistId = Artist.ArtistId`
`ORDER BY Album.AlbumId`
`LIMIT 5;`

`╭───────────────────────────────────────┬───────────╮`
`│                 Title                 │  artist   │`
`╞═══════════════════════════════════════╪═══════════╡`
`│ For Those About To Rock We Salute You │ AC/DC     │`
`│ Balls to the Wall                     │ Accept    │`
`│ Restless and Wild                     │ Accept    │`
`│ Let There Be Rock                     │ AC/DC     │`
`│ Big Ones                              │ Aerosmith │`
`╰───────────────────────────────────────┴───────────╯`

Step five is a CTE, a common table expression. It names a query with WITH so you can use it like a table in the next query. This one sums revenue per country, then picks the top three:

`WITH country_revenue AS (`
`  SELECT BillingCountry AS country, ROUND(SUM(Total), 2) AS revenue`
`  FROM Invoice GROUP BY BillingCountry`
`)`
`SELECT country, revenue FROM country_revenue`
`ORDER BY revenue DESC LIMIT 3;`

`╭─────────┬─────────╮`
`│ country │ revenue │`
`╞═════════╪═════════╡`
`│ USA     │  523.06 │`
`│ Canada  │  303.96 │`
`│ France  │   195.1 │`
`╰─────────┴─────────╯`

Step six is window functions. RANK() OVER (PARTITION BY Country ...) ranks customers inside their own country without collapsing rows the way GROUP BY does. Here we keep the top spender per country:

`WITH totals AS (`
`  SELECT c.CustomerId, c.Country,`
`         c.FirstName || ' ' || c.LastName AS customer,`
`         ROUND(SUM(i.Total), 2) AS total_spent`
`  FROM Customer c JOIN Invoice i USING (CustomerId)`
`  GROUP BY c.CustomerId`
`), ranked AS (`
`  SELECT *, RANK() OVER (PARTITION BY Country ORDER BY total_spent DESC) AS country_rank`
`  FROM totals`
`)`
`SELECT Country, customer, total_spent, country_rank`
`FROM ranked WHERE country_rank = 1`
`ORDER BY Country LIMIT 5;`

`╭───────────┬─────────────────┬─────────────┬──────────────╮`
`│  Country  │    customer     │ total_spent │ country_rank │`
`╞═══════════╪═════════════════╪═════════════╪══════════════╡`
`│ Argentina │ Diego Gutiérrez │       37.62 │            1 │`
`│ Australia │ Mark Taylor     │       37.62 │            1 │`
`│ Austria   │ Astrid Gruber   │       42.62 │            1 │`
`│ Belgium   │ Daan Peeters    │       37.62 │            1 │`
`│ Brazil    │ Luís Gonçalves  │       39.62 │            1 │`
`╰───────────┴─────────────────┴─────────────┴──────────────╯`

Once these six steps feel normal, the rest of SQL is details: data types, NULL handling, and the differences between databases. Our guide to [SQL data types](https://www.erathos.com/en/blog/data-types-in-sql?utm_source=blog&utm_medium=organic&utm_content=bydefault&utm_campaign=learn-sql-for-free) covers the first of those.

## Which free SQL courses are worth your time?

For a complete beginner, SQLBolt teaches the basics in the browser with no signup, Khan Academy's Intro to SQL adds video, and CS50 SQL from Harvard goes deepest for free. Kaggle's Intro to SQL is the pick if you want to learn on BigQuery, a real cloud warehouse.

Course

Cost

Database it teaches on

Format

Length stated by the course

[SQLBolt](https://sqlbolt.com/)

Free

SQLite-style, in-browser

Interactive lessons and exercises

Not stated

[Khan Academy: Intro to SQL](https://www.khanacademy.org/computing/computer-programming/sql)

Free

In-browser

Videos plus interactive challenges

Not stated

[CS50 SQL (Harvard)](https://cs50.harvard.edu/sql/)

Free; certificate via edX is paid

SQLite, plus PostgreSQL and MySQL later

Lectures, problem sets, final project

Seven weeks of material

[Kaggle: Intro to SQL](https://www.kaggle.com/learn/intro-to-sql)

Free

Google BigQuery

Notebook tutorials and exercises

3 hours

[Codecademy: Learn SQL](https://www.codecademy.com/learn/learn-sql)

Free lessons; certificate is paid

In-browser

Interactive lessons

5 hours

[Mode SQL Tutorial](https://mode.com/sql-tutorial/)

Free

Mode's own editor

15 basic, 20 intermediate, 9 advanced lessons, plus 8 analytics lessons

Not stated

[freeCodeCamp: Relational Database](https://www.freecodecamp.org/learn/relational-database/)

Free

PostgreSQL in a terminal

Project-based, uses Bash and VS Code

Not stated

[freeCodeCamp SQL video course](https://www.youtube.com/watch?v=HXV3zeQKqGY)

Free

MySQL

Single YouTube video

4 hours 20 minutes

[W3Schools SQL](https://www.w3schools.com/sql/)

Free

MySQL, SQL Server, PostgreSQL, Oracle, Access

Reference pages with Try It editor

Not stated

[SQLZoo](https://sqlzoo.net/wiki/SQL_Tutorial)

Free, login optional

In-browser

Wiki-style tutorial with exercises

Not stated

A few notes on picking. SQLBolt is the fastest way to write your first query, because the lessons start with parts of a SELECT and the exercises run on the same page. CS50 SQL is the only one on the list with graded problem sets and a final project; submitting them needs a free edX account. freeCodeCamp's Relational Database course is the odd one out: it teaches PostgreSQL through a terminal alongside Bash, and freeCodeCamp says that section is no longer being updated.

The freeCodeCamp video course has over 20 million views and runs 4 hours and 20 minutes. It's a good background lecture, but a video alone won't build the habit of typing queries. Pair it with one of the interactive options.

## Where can you practice SQL for free?

For free SQL practice, use LeetCode's SQL 50 study plan for interview-style problems, PostgreSQL Exercises for a single realistic dataset that goes up to window functions and recursive queries, and HackerRank's SQL domain for graded problems sorted by topic. All three run in the browser with no install.

Practice site

Cost

Database

What you get

[LeetCode SQL 50](https://leetcode.com/studyplan/top-sql-50/)

Free study plan

Several engines to choose from

50 SQL questions built as an interview prep plan

[PostgreSQL Exercises](https://pgexercises.com/)

Free (content is CC BY-SA 3.0)

PostgreSQL

Questions from SELECT and WHERE through joins, aggregation, window functions, and recursive queries, all on one country-club dataset

[HackerRank SQL](https://www.hackerrank.com/domains/sql)

Free

Several engines

Problems grouped into Basic Select, Advanced Select, Aggregation, Basic Join, Advanced Join, and Alternative Queries, tagged Easy to Hard

[Stack Exchange Data Explorer](https://data.stackexchange.com/)

Free

SQL Server (T-SQL)

Write queries against real public Stack Overflow data

Stack Exchange Data Explorer is the most interesting of the four because the data is real and large. It's an [open source tool for running arbitrary queries](https://data.stackexchange.com/help) against public data from every Stack Exchange site, and you can start from queries other people have shared.

When you want to type SQL without setting anything up, browser sandboxes give you an empty database:

Sandbox

Engines available

[sqliteonline.com](https://sqliteonline.com/)

SQLite, MariaDB, PostgreSQL, MS SQL

[sqlfiddle.com](https://sqlfiddle.com/)

SQL Server, SQLite, PostgreSQL, MySQL, MariaDB, Oracle

[db-fiddle.com](https://www.db-fiddle.com/)

Free fiddles; private fiddles need the paid PRO tier

[shell.duckdb.org](https://shell.duckdb.org/)

DuckDB, with sample datasets loaded (NYC Taxi in Parquet, Star Trek CSV, train services)

## Which free database should you install to learn SQL?

Install SQLite first, then DuckDB. SQLite is public domain, ships as a single command-line program, and reads the Chinook file used in this article with no server to configure. DuckDB is also a single file, and it can query a CSV directly with no import step.

[SQLite is in the public domain](https://sqlite.org/copyright.html), so there's no license to accept. The [sqlite3 command-line shell](https://sqlite.org/cli.html) opens a database file or an in-memory one and lets you type queries at a prompt. If you'd rather click than type, [DB Browser for SQLite](https://sqlitebrowser.org/) is a free desktop app with a spreadsheet-like view of the tables.

To reproduce the examples above, download the Chinook SQLite file from the project's releases page and open it:

`curl -fL `[`https://github.com/lerocha/chinook-database/releases/download/v1.4.5/Chinook_Sqlite.sqlite`](https://github.com/lerocha/chinook-database/releases/download/v1.4.5/Chinook_Sqlite.sqlite)` \`
`  -o Chinook_Sqlite.sqlite`
`sqlite3 Chinook_Sqlite.sqlite`

`Then turn on headers and the box output style, and every query in this article will print the same way:`

`.headers on`
`.mode box`
`SELECT COUNT(*) AS customers FROM Customer;`

The [DuckDB CLI](https://duckdb.org/docs/stable/clients/cli/overview.html) is a single, dependency-free executable precompiled for Windows, Mac, and Linux. Its best trick for a learner is querying files directly. We exported the Customer table to a CSV from SQLite, then asked DuckDB to group it without creating a table:

`SELECT Country, COUNT(*) AS n`
`FROM 'customers.csv'`
`GROUP BY Country`
`ORDER BY n DESC`
`LIMIT 5;`

`┌─────────┬───────┐`
`│ Country │   n   │`
`│ varchar │ int64 │`
`├─────────┼───────┤`
`│ USA     │    13 │`
`│ Canada  │     8 │`
`│ Brazil  │     5 │`
`│ France  │     5 │`
`│ Germany │     4 │`
`└─────────┴───────┘`

That means any CSV you already have (an export from a spreadsheet, a bank statement, a sales report) becomes a practice database in one line.

When you want to practice on a database that runs in the cloud, the free tiers below cost nothing and need no credit card for the BigQuery sandbox:

Free cloud database

What the free tier includes

Watch out for

[BigQuery sandbox](https://docs.cloud.google.com/bigquery/docs/sandbox)

1 TiB of query processing per month, 10 GiB of storage, no credit card

The 10 GiB storage limit is lifetime and is not refunded when you delete data

[Supabase Free](https://supabase.com/pricing)

$0, PostgreSQL, unlimited API requests

Projects pause after 1 week of inactivity; limit of 2 active projects

[Neon Free](https://neon.com/pricing)

$0, PostgreSQL, 100 projects, 100 compute-hours per project per month

0.5 GB of storage per project

BigQuery is the one we'd pick for a learner who wants to see what a data warehouse feels like. Kaggle's Intro to SQL course runs on it, and Google hosts public datasets you can query right away.

## Which free datasets can you practice SQL on?

Chinook, Sakila, and Northwind are the classic small sample databases, and the Stack Exchange Data Explorer, BigQuery public datasets, and NYC taxi trip records give you real data at scale. Start small so you can check your answers by hand, then move to the large ones.

Dataset

Size and shape

Where to get it

Chinook

11 tables of a digital music store: 59 customers, 412 invoices, 3,503 tracks, 275 artists

[GitHub releases](https://github.com/lerocha/chinook-database), scripts for six database engines

Sakila

MySQL's official sample database, a DVD rental store

[MySQL docs](https://dev.mysql.com/doc/sakila/en/)

Northwind

Microsoft's classic trading-company sample

[Microsoft SQL Server samples on GitHub](https://github.com/microsoft/sql-server-samples/tree/master/samples/databases/northwind-pubs)

Stack Exchange data

Live public data from every Stack Exchange site

[data.stackexchange.com](https://data.stackexchange.com/), queried in T-SQL

BigQuery public datasets

Many large public datasets hosted by Google

[cloud.google.com/bigquery/public-data](https://cloud.google.com/bigquery/public-data), free within the sandbox limits

NYC taxi trip records

Pickup and drop-off times and locations, distances, fares, payment types, in Parquet files

[NYC Taxi and Limousine Commission](https://www.nyc.gov/site/tlc/about/tlc-trip-record-data.page)

The Chinook row counts above come from running COUNT(\*) on the SQLite file. Small numbers like these are the point: when a GROUP BY says the USA has 13 customers, you can scroll the Customer table and count them yourself.

## Which SQL dialect should you learn first?

Learn on SQLite or PostgreSQL first. SQLite is the smallest install, and PostgreSQL is the most used database in the [2025 Stack Overflow survey](https://survey.stackoverflow.co/2025/technology) at 55.6% of all respondents. Both use standard syntax for the things that differ most between databases: row limits, string joining, and quoting names.

The core of SQL (SELECT, WHERE, GROUP BY, JOIN, CTEs, window functions) is the same everywhere. The differences that catch beginners are in the small stuff:

Task

SQLite / PostgreSQL

MySQL

SQL Server

Return the first 5 rows

LIMIT 5 (PostgreSQL also accepts [FETCH FIRST 5 ROWS ONLY](https://www.postgresql.org/docs/current/sql-select.html))

LIMIT 5

[SELECT TOP 5](https://learn.microsoft.com/en-us/sql/t-sql/queries/top-transact-sql)

Join two strings

The double-pipe operator, as in FirstName \\

\\

' ' \\

\\

LastName

CONCAT(); the double pipe means OR unless the [PIPES\_AS\_CONCAT](https://dev.mysql.com/doc/refman/8.4/en/sql-mode.html) mode is on

CONCAT() or +

Quote a column name

Double quotes

[Backticks](https://dev.mysql.com/doc/refman/8.4/en/identifiers.html), unless ANSI\_QUOTES mode is on

[Square brackets or double quotes](https://learn.microsoft.com/en-us/sql/relational-databases/databases/database-identifiers)

Today's date

[date('now')](https://sqlite.org/lang_datefunc.html) in SQLite, CURRENT\_DATE in PostgreSQL

[CURDATE()](https://dev.mysql.com/doc/refman/8.4/en/date-and-time-functions.html)

[GETDATE()](https://learn.microsoft.com/en-us/sql/t-sql/functions/getdate-transact-sql) returns a datetime

The string concatenation row is the one that bites most often. This query works the same in SQLite and DuckDB:

[`SELECT FirstName || ' ' || LastName AS full_name`
`FROM Customer`
`LIMIT 3;`](https://)

[`╭───────────────────╮`
`│     full_name     │`
`╞═══════════════════╡`
`│ Luís Gonçalves    │`
`│ Leonie Köhler     │`
`│ François Tremblay │`
`╰───────────────────╯`](https://)

In MySQL with default settings, the same double pipe is a logical OR, so you'd write CONCAT(FirstName, ' ', LastName) instead. DuckDB accepts both forms and returned the same three names for each.

## How long does it take to learn SQL?

The free courses themselves put the basics at a few hours and a full course at a few weeks. Kaggle's Intro to SQL is listed at [3 hours](https://www.kaggle.com/learn/intro-to-sql), Codecademy's Learn SQL at [5 hours](https://www.codecademy.com/learn/learn-sql), and CS50 SQL is [seven weeks of material](https://cs50.harvard.edu/sql/) with problem sets.

Those numbers cover the lessons. Getting comfortable comes from repetition on data you care about, which is why the practice sites and datasets above matter more than which course you choose. A workable plan is one interactive course to cover the six steps, then a problem set (LeetCode SQL 50 or PostgreSQL Exercises) until joins and GROUP BY stop needing thought, then one real dataset you explore with no assignment at all.

## Where does SQL take you next?

Once you can write these queries, the next question is where the data you want to query is. At most companies it's spread across a CRM, a payments tool, a support desk, and a few spreadsheets. The usual fix is to copy all of it into one warehouse (BigQuery, Snowflake, Redshift, or Databricks) and point your SQL at that. Our guide on [data centralization without a dedicated data team](https://www.erathos.com/en/blog/data-centralization-without-a-dedicated-team?utm_source=blog&utm_medium=organic&utm_content=bydefault&utm_campaign=learn-sql-for-free) walks through that setup.

The loading step is what data teams call ELT: extract from the source, load into the warehouse, then transform with SQL. Our [ETL vs ELT comparison](https://www.erathos.com/en/blog/etl-vs-elt-key-differences?utm_source=blog&utm_medium=organic&utm_content=bydefault&utm_campaign=learn-sql-for-free) explains why the transform moved to the end, and why that made SQL the main skill for working with warehouse data. Tools like [Metabase](https://www.erathos.com/en/blog/what-is-metabase?utm_source=blog&utm_medium=organic&utm_content=bydefault&utm_campaign=learn-sql-for-free) then let you turn those queries into dashboards.

Erathos is the loading layer in that stack. It connects to your sources and delivers the tables into your warehouse, so the SQL you just learned has something real to run against. [Try Erathos free for 14 days](https://app.erathos.com/signup?utm_source=blog&utm_medium=organic&utm_content=bydefault&utm_campaign=learn-sql-for-free).
