Home › Guides › How to learn SQL in 8 weeks
Tech Explained · 2026How to Learn SQL in 8 Weeks: A 2026 Roadmap With Real Queries and Free Practice
How to learn SQL in 8 weeks works if you practise queries instead of watching them: spend roughly 60 hours in total, start in SQLite with nothing to install, learn SELECT, WHERE, JOIN, GROUP BY and window functions in that order, and finish with two query projects you can defend in an interview.
- Eight weeks is enough for job-ready analytical SQL at about 8 hours a week. It is not enough for database administration or tuning at scale.
-
Start in SQLite, not PostgreSQL. Python ships the
sqlite3module, so you can load a CSV and run your first join in under ten minutes with no server and no Docker. - Five clauses carry most real work: SELECT, WHERE, JOIN, GROUP BY and ORDER BY. Window functions are the sixth, and they are the dividing line between a beginner and a hireable analyst.
- Dialects differ in small, painful ways. A query that works in PostgreSQL 18 breaks in SQL Server on the LIMIT clause alone, so learn one engine properly and keep a translation table.
- Two projects beat six tutorials. Interviewers ask about the join you got wrong, not the course you finished.
You have a CSV open in Excel, 140,000 rows, and the pivot table has been spinning for forty seconds. Someone on the call says "just pull it with SQL" and you nod, because saying no is worse. That gap, between knowing SQL exists and being able to answer a question with it by Thursday, is what this plan closes. The scenario running through this guide is a Pune-based support analyst with roughly eight spare hours a week and no database access at work yet. If that is close enough to you, the weeks below will fit.
How to Learn SQL Without Installing Anything (Week 0, 20 Minutes)
Nearly every SQL for beginners guide starts with an install, and nearly every reader loses their first weekend to it. They pick PostgreSQL because a forum thread said so, fight a Docker volume, and never write a SELECT. Skip that. SQLite is a single file, it is already inside Python, and it speaks enough standard SQL to carry you to week six. Download any CSV you care about, then do this:
# one file, no server, no password
sqlite3 shop.db
sqlite> .mode csv
sqlite> .import orders.csv orders
sqlite> .headers on
sqlite> .mode column
sqlite> SELECT COUNT(*) FROM orders;
140238
sqlite> .schema orders
CREATE TABLE orders(order_id TEXT, city TEXT, amount TEXT, order_date TEXT);
Look at that last line, because it is your first real lesson. SQLite imported every column as TEXT, so SUM(amount) will quietly do the wrong thing and order_date > '2026-01-01' will work by accident, through string comparison. Column types are not a week seven detail. They are what makes your first number wrong. Declare the table before you import:
sqlite3 shop.db
sqlite> CREATE TABLE orders (
...> order_id TEXT PRIMARY KEY,
...> city TEXT NOT NULL,
...> amount REAL NOT NULL,
...> order_date TEXT NOT NULL -- ISO 8601, YYYY-MM-DD
...> );
sqlite> .mode csv
sqlite> .import --skip 1 orders.csv orders
sqlite> SELECT ROUND(SUM(amount), 2) FROM orders;
48219904.5
Versions barely matter here. The change log on sqlite.org lists 3.53.1, released on 5 May 2026, as the newest release, and notes that the planned 3.52.0 was withdrawn with its features folded into 3.53.0. Whatever ships with your operating system is fine for learning.
The 8-Week SQL Roadmap 2026, Week by Week
This SQL roadmap assumes eight hours a week, about 60 hours in total. Order matters more than pace: every week depends on the one before it, and the two weeks people skip, 3 and 7, are the two that show up in interviews.
The 8-week SQL plan
Each week ends in something you can run, not something you have watched.
SELECT, WHERE, ORDER BY, LIMIT
Load two CSVs into SQLite and answer ten questions about one table only. Deliverable: a .sql file with ten working queries and the row counts they return.
GROUP BY and aggregation
COUNT, SUM, AVG, MIN, MAX, plus HAVING. Deliverable: revenue by city by month, with a sanity check that the totals match SUM(amount) over the whole table.
JOINs, properly
INNER, LEFT, and the self join. Deliverable: deliberately break a join so it duplicates rows, then write down the row count before and after. This is the week that pays off for years.
Subqueries and CTEs
Rewrite three of your week 3 queries using WITH. Deliverable: one query that is four stacked CTEs and still readable six days later.
Dates, text, NULL and CASE
Date truncation, string splitting, COALESCE, and the three-valued logic that makes WHERE col != 'x' drop your NULL rows. Deliverable: a cohort table by signup month.
Move to PostgreSQL
Same queries, real server, real types. Deliverable: your week 5 cohort query running on Postgres with proper DATE and NUMERIC columns instead of TEXT.
Window functions
ROW_NUMBER, RANK, LAG, LEAD, running totals, and the OVER clause. Deliverable: month-over-month growth and a top-3-per-city ranking, both in one query each.
Project and EXPLAIN
Ship one of the three projects below, add an index, and read the plan before and after. Deliverable: a repo with a README that states the question each query answers.
Pacing assumes roughly 8 hours a week of hands-on querying, checked 2 November 2026.
Those 60 hours should not be spread evenly. Joins and window functions together deserve nearly half your practice time, because that is where correctness and employability both live.
Where 60 hours of SQL practice should go
Joins plus window functions are 45% of the effort and most of the interview.
Split reflects the clauses that appear in analyst job descriptions and interview rounds, as reviewed on 2 November 2026.
If you would rather not self-pace this, the SQL and Excel blocks of 360DT's live Data Analyst course cover weeks 1 through 7 of this plan in guided sessions, with the same queries reviewed line by line. Also read: our SQL commands cheat sheet for the syntax you will keep forgetting in weeks 1 and 2.
How to Learn SQL for Beginners: The Five Clauses That Do Most of the Work
SQL looks like English, and that is a trap, because it does not execute in the order you read it. You write SELECT first, but the engine resolves FROM and JOIN first, then WHERE, GROUP BY, HAVING, SELECT, and only then ORDER BY and LIMIT. That one fact explains most beginner errors, including why a column alias will not work in WHERE. Here is all of weeks 1 and 2 in one query: our Pune analyst wants the ten cities with the highest average order value in the last 90 days, counting only cities with enough orders to mean anything.
SELECT city,
COUNT(*) AS orders,
ROUND(AVG(amount), 2) AS avg_order_value
FROM orders
WHERE order_date >= DATE('now', '-90 days')
GROUP BY city
HAVING COUNT(*) >= 50
ORDER BY avg_order_value DESC
LIMIT 10;
Five clauses, one real question answered. WHERE filters rows before grouping, HAVING filters groups after. Swap them and you get an error or, worse, a plausible wrong answer.
The pipeline your query actually runs through
Knowing what happens after you press enter is what turns guessing into debugging. Your query is text until the parser turns it into a tree, the planner decides how to fetch rows, and the executor does the work against the heap and whatever indexes exist.
From your SQL text to a chart
EXPLAIN shows you the planner's decision, which is the only part you can influence from the query.
Simplified from the parse, plan, execute model documented by PostgreSQL and SQLite; checked 2 November 2026.
JOINs and the Grain Problem Nobody Warns You About
Week 3 is the week to slow down. A join does not add columns, it multiplies rows, and if the right-hand table holds two rows per key your revenue total doubles with no error message at all. Your manager will not catch it. You will, two weeks later, when finance disagrees. Build the habit now: count before, count after.
-- 1. what is the grain of each table?
SELECT COUNT(*), COUNT(DISTINCT order_id) FROM orders; -- 140238 | 140238
SELECT COUNT(*), COUNT(DISTINCT order_id) FROM order_items; -- 391044 | 140238
-- 2. so this join CANNOT be used for revenue totals
SELECT SUM(o.amount)
FROM orders o
JOIN order_items i ON i.order_id = o.order_id; -- wrong: 134 crore
-- 3. aggregate first, then join
WITH item_counts AS (
SELECT order_id, COUNT(*) AS items
FROM order_items
GROUP BY order_id
)
SELECT ROUND(SUM(o.amount), 2) AS revenue,
ROUND(AVG(c.items), 2) AS avg_items_per_order
FROM orders o
LEFT JOIN item_counts c ON c.order_id = o.order_id; -- right: 4.82 crore
That three-step pattern, check the grain, aggregate to the grain you need, then join, is worth more than anything else in this guide. It is also why star schemas exist: a well-built warehouse hands you one fact table at one grain, so you cannot make this mistake by accident.
-
LEFT JOIN plus a WHERE on the right table. You wrote LEFT JOIN to keep unmatched rows, then filtered
WHERE i.status = 'shipped', which silently turns it back into an inner join. Put that condition in the ON clause instead. -
COUNT(*) after a LEFT JOIN. It counts the join output, not your customers. Use
COUNT(DISTINCT o.order_id)when in doubt, and always be able to say which thing you are counting. -
NULL comparisons.
amount != 100drops every row where amount is NULL, because NULL is not equal to anything, including itself. Writeamount IS DISTINCT FROM 100in PostgreSQL, or wrap in COALESCE. -
Joining on a float or a formatted string. If the key is
'0012'in one table and12in the other, you get zero matches and no complaint from the database.
SQL Window Functions: What Separates Week 4 From Week 7
If you learn nothing else after joins, learn SQL window functions. They answer what aggregation cannot: ranking inside a group, comparing a row to the previous row, running totals. People used to solve these with correlated subqueries nobody could read. Here is one business question at two skill levels.
Week 2: what you can write
Monthly revenue. Correct, but it cannot compare months.
SELECT strftime('%Y-%m', order_date) AS mth,
ROUND(SUM(amount), 2) AS revenue
FROM orders
GROUP BY mth
ORDER BY mth;
mth revenue
2026-07 3914220.50
2026-08 4455109.75
2026-09 4201880.00
Run on the sample SQLite database used throughout this guide, 2 November 2026.
Week 7: what gets you hired
Same data, now with month-over-month growth in one pass.
WITH m AS (
SELECT strftime('%Y-%m', order_date) AS mth,
SUM(amount) AS revenue
FROM orders GROUP BY mth
)
SELECT mth,
ROUND(revenue, 2) AS revenue,
ROUND(100.0 * (revenue - LAG(revenue) OVER (ORDER BY mth))
/ LAG(revenue) OVER (ORDER BY mth), 1) AS mom_pct
FROM m ORDER BY mth;
mth revenue mom_pct
2026-07 3914220.50 NULL
2026-08 4455109.75 13.8
2026-09 4201880.00 -5.7
LAG returns NULL on the first row, which is correct and worth explaining in an interview.
The other window function to drill is ROW_NUMBER with PARTITION BY, which answers "top 3 products per city" in a way GROUP BY simply cannot:
WITH ranked AS (
SELECT city, product, SUM(amount) AS rev,
ROW_NUMBER() OVER (PARTITION BY city ORDER BY SUM(amount) DESC) AS rn
FROM orders GROUP BY city, product
)
SELECT city, product, ROUND(rev, 2) AS rev
FROM ranked WHERE rn <= 3 ORDER BY city, rn;
You cannot filter on rn in the same SELECT that defines it, because window functions are evaluated after WHERE. That is the execution order biting again. Wrap it in a CTE, every time.
Window functions are also where the certification syllabi start: both the Power BI data modelling work in the PL-300 track and the Spark SQL and T-SQL sections of a live Microsoft Fabric data engineering program assume you can write an OVER clause without looking it up.
Where to Practise SQL Free in 2026
None of this costs money. What you do need is a dataset with more than one table, because single-table practice teaches you nothing about joins.
| Option | What it is | Free limit | Best for |
|---|---|---|---|
| SQLite on your laptop | A single-file database, already inside Python as the sqlite3 module |
No limit, no account, no server | Weeks 1 to 5. Start here. |
| PostgreSQL locally | The real thing. Version 18 is the current stable line, with 18.6 the latest minor released on 13 August 2026 per postgresql.org | Free and open source | Week 6 onward, real types and real EXPLAIN |
| BigQuery sandbox | Google's warehouse with no billing account attached | Google's sandbox documentation states 10 GB of active storage and 1 TB of processed query data per month, with tables expiring after 60 days | Practising on large public datasets |
| Supabase free project | Hosted PostgreSQL with a web SQL editor | Third-party pricing trackers in 2026 consistently report 500 MB of database per project, and free projects pausing after a week of inactivity | Querying from another machine, sharing a database |
| DuckDB | An in-process engine that queries CSV and Parquet files directly | Free and open source | When your CSV is too big for Excel but too small for a warehouse |
One opinion, stated plainly: skip the gamified SQL apps in week 1. They train you to pattern-match a puzzle, and real analysis is never a puzzle with one answer. Load your own messy CSV instead, the one with trailing spaces and two spellings of Bengaluru, because cleaning that is the job. Also read: our DuckDB walkthrough if your files are Parquet rather than a database.
Dialects: where your query breaks when the engine changes
Learn one engine well and keep this table nearby. These five differences cause most of the confusion when you move from a tutorial to your employer's database.
| Task | PostgreSQL | MySQL | SQL Server | BigQuery |
|---|---|---|---|---|
| First 10 rows | LIMIT 10 |
LIMIT 10 |
SELECT TOP 10 |
LIMIT 10 |
| Join text | a || b |
CONCAT(a,b) |
a + b |
CONCAT(a,b) |
| Month bucket | DATE_TRUNC('month', d) |
DATE_FORMAT(d,'%Y-%m') |
DATETRUNC(month, d) |
DATE_TRUNC(d, MONTH) |
| Null fallback | COALESCE(a, 0) |
IFNULL(a, 0) |
ISNULL(a, 0) |
IFNULL(a, 0) |
| Integer division | 7/2 = 3 |
7/2 = 3.5 |
7/2 = 3 |
7/2 = 3.5 |
That last row has produced more wrong percentages than anything else here. In PostgreSQL and SQL Server, successes / total on two integer columns returns 0, not 0.42. Cast one side: successes * 1.0 / total.
Learn SQL alongside Excel, Python and Power BI, with your queries reviewed live
A 10-week live weekend program covering Python, SQL, advanced Excel and Power BI, with preparation for the Microsoft PL-300 certification. Includes hands-on projects, mentor support and placement guidance.
Explore the course
The Errors You Will Hit, and the Actual Fix
Keep this open in week 2. You will see every one of these verbatim, and the wording is more helpful than it looks once you know what the engine is objecting to.
| What you see | What it really means | Fix |
|---|---|---|
column "city" must appear in the GROUP BY clause |
You selected a column that is neither grouped nor aggregated | Add it to GROUP BY, or wrap it in MIN, MAX or an aggregate you can justify |
column "avg_order_value" does not exist in a WHERE clause |
Aliases are created in SELECT, which runs after WHERE | Repeat the expression in WHERE, or wrap the query in a CTE and filter outside |
aggregate functions are not allowed in WHERE |
You meant to filter groups, not rows | Move the condition to HAVING |
more than one row returned by a subquery used as an expression |
Your scalar subquery is not scalar | Add LIMIT 1 with an ORDER BY you can defend, or convert it to a join |
| Totals suddenly inflated, no error at all | A join changed the grain | COUNT(*) before and after the join, then aggregate the many-side first |
operator does not exist: text >= date |
Your date column is stored as text | Cast it, or fix the column type. This is why week 6 moves to PostgreSQL |
One honest caveat
SQL on its own will not get you an analyst job in 2026, and anyone selling an eight-week plan as a career guarantee is selling you something. Postings that ask for SQL almost always ask for Power BI or Tableau beside it, plus enough Excel to survive the first week and enough Python to clean a file. SQL is the entry ticket, not the whole stack. It is also genuinely bad at some things people try to use it for: complex row-by-row business logic, anything that needs loops, and statistics beyond averages and percentiles. When a query grows to 400 lines of nested CASE statements, the answer is not better SQL. It is to move that logic into a modelling layer such as dbt or into Python.
SQL Practice Projects: Three Builds That Survive an Interview
SQL practice projects are where the eight weeks turn into something you can show. Week 8 exists to produce exactly one artefact. Pick the one you are actually curious about, because curiosity is what carries you through the boring part of cleaning the data.
- Retail cohort analysis. Two tables, customers and orders. Produce a monthly cohort retention grid using DATE_TRUNC and a self join on month offset. What the interviewer asks: "how did you handle customers who bought twice in the same month?"
- Public transport delay analysis. Load an open GTFS feed or any published timetable plus actuals. Produce average delay by route and hour, with a window function that flags each route's worst hour. What the interviewer asks: "what is the grain of your fact table, and what did you do with missing arrivals?"
- Your own expenses. Export 24 months of bank statements to CSV, categorise with CASE and a lookup table, then produce month-over-month change by category with LAG. What the interviewer asks: "how did you categorise the 8% that did not match any rule?" Have an answer, because that 8% is the whole point.
Write a README that states, in one line before each query, the question it answers. Reviewers read that README and little else, and a repo of unexplained .sql files reads as homework. Also read: 20 SQL interview questions with model answers, which map almost exactly onto weeks 3 and 7.
Week 8: add an index and read the plan
Finish by making one query faster, so you can say something concrete when asked about performance:
-- before
EXPLAIN ANALYZE SELECT * FROM orders WHERE city = 'Pune';
-- Seq Scan on orders (cost=0.00..3214.98 rows=1402 width=64)
-- Filter: (city = 'Pune'::text)
CREATE INDEX idx_orders_city ON orders (city);
ANALYZE orders;
-- after
EXPLAIN ANALYZE SELECT * FROM orders WHERE city = 'Pune';
-- Bitmap Heap Scan on orders (cost=32.11..812.44 rows=1402 width=64)
-- Recheck Cond: (city = 'Pune'::text)
-- -> Bitmap Index Scan on idx_orders_city
The numbers you see will differ. What matters is that you can describe the change from a sequential scan to an index scan and explain why an index on a column with three distinct values would not have helped. If you want this on a current engine, note that PostgreSQL 18, released on 25 September 2025, turns data checksums on by default and adds a built-in uuidv7() function, and that postgresql.org's news page shows PostgreSQL 19 reaching release candidate 1 on 15 October 2026 with general availability targeted for 19 November 2026. If your workplace is still on PostgreSQL 14, flag it: the project's own schedule has that branch stopping fixes on 12 November 2026.
Where SQL Takes You Next
By week 8 our Pune analyst can answer questions nobody else on the team can answer without a BI licence, which is a real change in standing. Three routes open from there. The analyst route adds Power BI and DAX, which is what the PL-300 aligned Data Analyst program is built around. The engineering route adds pipelines and warehouse design, where DP-700 and Microsoft Fabric sit. The third is newer: systems that generate SQL still need someone who can tell when the generated query is wrong, which is a large part of RAG and AI agent engineering work, and AWS architecture work turns on choosing between RDS, Aurora and Athena by query pattern. The full certifications overview shows how they line up.
In your position I would not try to choose that route now. I would do the eight weeks, ship one project, and let the work tell me which part I actually enjoyed, because almost nobody picks correctly from the outside. Then sit in on a free webinar or a demo class on whichever route still looks interesting, and spend money only after that. Eight weeks and one honest project is a far better filter than any amount of reading about careers.
Related guides
- What Is Text-to-SQL in 2026? Read this once you can write SQL, so you can judge when a generated query is quietly wrong.
- Data Analyst Roadmap 2026 The wider seven-step plan that this eight-week SQL block fits into.
- Data Analyst Salary in India 2026 What advertised pay bands look like once SQL stops being the bottleneck.
- PL-300 vs DP-700 in 2026 Which Microsoft data certification to point your new SQL skills at first.
- Data Analyst Jobs in Gurgaon 2026 A concrete look at which employers test SQL in the first round.
- What Is a Data Warehouse? Where the tables you query actually come from, and why their shape makes your joins easy or awful.
Frequently asked questions
How long does it take to learn SQL from scratch?
About 60 hours of hands-on querying, which is eight weeks at 8 hours a week, gets you to the level analyst job descriptions describe: joins, aggregation, CTEs and window functions. Reading syntax is faster than that. Being trusted with a number is not.
How to learn SQL for a data analyst job without any coding background?
SQL is the friendliest place to start precisely because there are no loops, no classes and no environment to configure. Load a CSV into SQLite, answer ten questions about it in week 1, and treat every wrong answer as the lesson. No prior programming is needed.
Should I learn MySQL or PostgreSQL first?
PostgreSQL, if you must pick one, because its window function and CTE support is the most complete and its error messages teach you the most. But start in SQLite for the first five weeks, then move to PostgreSQL in week 6 when types and EXPLAIN start to matter.
Is SQL enough to get a job in 2026?
Rarely on its own. Analyst postings pair SQL with Power BI or Tableau, Excel, and basic Python. Treat SQL as the thing that gets your CV read and the BI tool as the thing that gets you shortlisted.
What are the most important SQL topics for interviews?
Joins and their effect on row counts, GROUP BY with HAVING, CTEs, and window functions: ROW_NUMBER with PARTITION BY, LAG, and running totals. A second-round question about NULL handling or duplicate rows is close to guaranteed.
Do I need to learn SQL if AI can write queries now?
Yes, and arguably more than before. A model will happily produce a join that doubles your revenue total and present it confidently. Someone has to read the query, check the grain and sign off on the number, and that person needs to know SQL.
What free datasets should I practise SQL on?
Anything with at least two related tables. Public transport timetables, government open data portals, and your own bank statements all work. Avoid single-table toy datasets, because they teach nothing about joins, which is where the real difficulty sits.
Can I learn SQL and Power BI at the same time?
Better to stagger them. Get through week 3 of this plan, joins and grain, before you start building visuals, otherwise you will build dashboards on top of inflated numbers and not know why the totals look high.
About this guide. 360 Digital Transformation is an Anthropic Partner and a Microsoft Authorized Training Partner. Other certification bodies, vendors and employers named here are not affiliated with us. Tools and versions change quickly; commands and figures cited were checked on 2 November 2026.




