Learn data by catching the right fireflies.

Each level is a real ticket from a colleague at Harbor & Pine, a home-goods store. Write the SQL or pandas, press Run, and watch your lantern light up.

SQL

46 levels
SELECT name, price
FROM products;
Play SQL level 1

Python

46 levels
products[["name", "price"]]
Play Python level 1
  • Runs in your browser
  • No signup
  • About 3 minutes a level

How a level works

Three steps, about three minutes. The same in SQL and in Python.

  1. Read the ticket

    A colleague asks a real question: a sales number, a list of customers, a cleanup. Mote brings it to you with a short goal list.

  2. Write the query

    SQL or pandas, in a real editor, on the store's real tables. The starter is already there, and the lesson sits next to it.

  3. Press Run

    Your result is checked against the answer, so any correct query passes. Then the stars: solved, no hints, right on the first run.

All levels

Two tracks, equal from day one. Every SQL and Python level is open; play them in any order.

Casework

3 cases · 6 levels · each opens when you finish its chapters in both tracks

Real analyst cases solved twice, in SQL and in pandas, on the same Harbor & Pine data. Each case opens when both tracks reach it.

About the dataset

Harbor & Pine is a fictional US online store for furniture, lighting and home goods. Three years of orders, 2023 to 2025, with the mess real data has: missing values, stray spaces, duplicate customers. SQL and Python levels use the same 8 tables.

customers2,018 rows · 9 columns
Who buys: city, state, signup date, consumer or business, how they found the store.
products120 rows · 8 columns
The catalog: category, price, cost (sometimes missing), launch date, still on sale or not.
orders12,000 rows · 7 columns
One row per order: when, which channel, status, shipping fee, coupon.
order_items30,338 rows · 6 columns
The lines inside each order: product, quantity, price paid, discount.
returns1,673 rows · 5 columns
What came back, why, and how much was refunded.
employees60 rows · 8 columns
The team, with departments, titles, salaries and who reports to whom.
web_sessions40,000 rows · 7 columns
Site visits: device, traffic source, pages viewed, whether it converted.
marketing_spend3,276 rows · 3 columns
Daily spend per marketing channel, for cost-per-conversion work.

Questions

Do I need to install anything?

No. SQL runs in DuckDB and Python runs in Pyodide, both inside your browser tab. The first Python level downloads about 12 MB once; after that it starts in seconds.

Which SQL dialect is it?

DuckDB, which follows PostgreSQL closely. Everything you learn here (SELECT, JOINs, GROUP BY, CTEs, window functions) works the same in PostgreSQL, and with small changes in MySQL, SQL Server and BigQuery.

Which one should I learn first, SQL or Python?

Either. The two tracks are independent and both open from the first level. Many analysts learn them side by side, and the casework track asks for both on the same questions.

Is my progress saved?

Yes, in this browser. There is no account. You can download your progress as a file from the Progress page and import it on another device.

How are answers checked?

Your result is compared with the expected output, not your code with ours. Any query or pandas code that returns the right table passes, and a wrong answer tells you what is off: missing columns, extra rows, a value that is too high.

Is it free?

Yes. Every level in both tracks and every case is free to play, with no signup.