LEARN BY QUERYING

Practice SQL with SQLite

Twenty-eight exercises across sales, inventory and analytics. Start with SELECT and work up to JOINs and subqueries. Every exercise has a hint, a solution and an answer check that runs locally in your browser. No account required.

Follow a learning path · Explore all three datasets

Start with the sample shop

customers → orders → order_items ← products. There are 8 customers, 12 orders, 17 order items and 6 products. Use the Schema tab to inspect every column.

  1. Select customer names

    Return name and country for every customer, ordered by id.

  2. Filter by country

    Return name for customers in India, ordered by id.

  3. Compare numbers

    Return name and price for products costing more than 60, ordered by price ascending, then id.

  4. Order by descending price

    Return name and price for all products, most expensive first, then id.

  5. Find the top three

    Return name and price for the three most expensive products, then id for ties.

  6. Find unique categories

    Return each distinct product category in alphabetical order.

  7. Count orders

    Return the total number of orders in one column.

  8. Sum order totals

    Return the sum of all order totals in one column.

  9. Calculate an average

    Return the average product price rounded to two decimal places.

  10. Group orders by status

    Return status and order count, ordered alphabetically by status.

  11. Filter aggregated groups

    Return customer_id and order count for customers with more than one order, ordered by customer_id.

  12. Connect customers and orders

    Return order id and customer name for every order, ordered by order id.

  13. Count orders per customer

    Return customer name and their order count for every customer, ordered by customer id.

  14. Find missing contact details

    Return names of customers whose email is NULL, ordered by id. The sample may return no rows.

  15. Replace missing values

    Return name and email, replacing NULL email with Unknown, ordered by id.

  16. Match part of a name

    Return product names containing the word Desk, ordered by id.

  17. Choose a price range

    Return name and price for products priced between 30 and 90 inclusive, ordered by id.

  18. Label expensive products

    Return name and a label: Premium when price is at least 80, otherwise Standard. Order by id.

  19. Compare against the average

    Return names of products priced above the average product price, ordered by id.

  20. Count units sold

    Return product name and total quantity sold, ordered by product id.

  21. Find stock shortages

    Return warehouse name, item name and quantity where quantity is below reorder_level, ordered by warehouse id and item id.

  22. Find items without stock records

    Return item names with no stock row, ordered by item id.

  23. Total stock including missing items

    Return every item name and total quantity, using zero for missing stock, ordered by item id.

  24. Calculate a running stock balance

    Return movement id, item id, warehouse id and running balance ordered by movement id. Calculate balances separately for each item and warehouse.

  25. Count daily active users

    Return date and distinct active user count for each day, ordered by date.

  26. Analyze device usage from JSON

    Return device and event count, ordered by device.

  27. Find inactive users

    Return user id and country for users without any events, ordered by user id.

  28. Rank event types per country

    Return country, event name, event count and rank within country by count descending. Use DENSE_RANK and order by country then event name.

Open the playground · Learn how JOINs work · Format a query