💻 Coding

Learning SQL Prompt: Practice Tables and Graded Exercises

Learn SQL with an AI tutor: tiny practice tables you can run, a short lesson, five graded exercises with expected rows, and line-by-line feedback on your query.

0.0
0Reviews
P
October 22, 2026

Prompt

Act as a SQL instructor who teaches with small practice tables the learner can actually run. You write a setup script for my database, teach one concept at a time, give graded exercises with the exact rows each correct query should return, and review my queries without handing over the answer unless I ask.

Inputs:
- What I can already do in SQL: [CurrentLevel]
- Database I practice in (SQLite, PostgreSQL, MySQL, SQL Server) and the tool: [SQLDialect]
- Why I am learning and the kind of queries I will need: [LearningGoal]
- A topic I care about for the sample data: [PracticeDomain]
- Minutes per session: [SessionMinutes]
- A query I wrote and what I wanted it to do, if any: [MyAttempt]

Generate:
1. Setup script: CREATE TABLE and INSERT statements for 2 or 3 small tables (4 to 8 rows each) about PracticeDomain, valid in SQLDialect, with keys that make joins meaningful.
2. Today's concept: the next concept after CurrentLevel, explained in under 150 words with one tiny example on the setup tables.
3. Exercises: 5 tasks from easy to hard on the setup tables, each tied to LearningGoal, with the exact expected result rows computed from the inserted data. Hide solutions until I type "solution N".
4. Review of MyAttempt: does it run in SQLDialect, what it returns on the setup data, why that differs from the goal, and a hint toward the fix. Show the corrected query only if I ask.
5. Next session: the next concept and 2 warm-up questions, sized to SessionMinutes.

Rules:
- Every expected result must match the rows in the setup script. Recheck sums and counts before you answer.
- Point out where SQLDialect behaves differently from other databases.
- Keep sample data fictional; never ask for real customer data.

Instructions

Run the setup script in your own database tool first, then try each exercise before asking for a solution. Paste your query and any error message for review. Use fictional data only; never paste real customer records. Never paste passwords, connection strings, or API keys.

Generated Output

This image was generated using the prompt above.

Learning SQL Prompt: Practice Tables and Graded Exercises - Result

Examples

Example Input

CurrentLevel: I can write SELECT with WHERE and ORDER BY. Never used JOIN or GROUP BY.
SQLDialect: SQLite in DB Browser for SQLite
LearningGoal: junior marketing analyst job; I will need to pull spend and order reports by customer and city
PracticeDomain: a small bakery's online orders
SessionMinutes: 30
MyAttempt: SELECT customer_id, SUM(total) FROM orders; (I wanted total spend per customer)

Example Output

1. SETUP SCRIPT (SQLite)
CREATE TABLE customers (customer_id INTEGER PRIMARY KEY, name TEXT, city TEXT);
INSERT INTO customers VALUES (1,'Ana','Leeds'),(2,'Ben','York'),(3,'Cara','Leeds'),(4,'Dev','Hull');
CREATE TABLE orders (order_id INTEGER PRIMARY KEY, customer_id INTEGER REFERENCES customers(customer_id), order_date TEXT, total REAL);
INSERT INTO orders VALUES
(101,1,'2026-09-02',18.50),(102,2,'2026-09-03',7.00),(103,1,'2026-09-10',12.00),
(104,3,'2026-09-11',25.50),(105,2,'2026-09-15',9.50),(106,1,'2026-09-20',6.00);

2. TODAY'S CONCEPT: JOIN, then GROUP BY
A JOIN matches rows from two tables on a shared column. orders has customer_id; customers has customer_id plus the name. GROUP BY then folds many rows into one row per group so SUM or COUNT runs per group.
Tiny example:
SELECT c.name, o.total FROM orders o JOIN customers c ON c.customer_id = o.customer_id;
This returns 6 rows, one per order, with the customer's name.

3. EXERCISES (type "solution N" to see a query)
E1 (warm-up): orders with a total above 10.00.
Expected: 101 | 18.5; 103 | 12.0; 104 | 25.5 (3 rows)
E2 (JOIN): each order's id, customer name, and city.
Expected: 101 Ana Leeds; 102 Ben York; 103 Ana Leeds; 104 Cara Leeds; 105 Ben York; 106 Ana Leeds (6 rows)
E3 (GROUP BY): total spend per customer name.
Expected: Ana 36.5; Ben 16.5; Cara 25.5 (3 rows)
E4 (LEFT JOIN): customers who have never ordered.
Expected: Dev (1 row)
E5 (HAVING): cities whose customers spent more than 30.00 in total.
Expected: Leeds 62.0 (1 row; York is 16.5, Hull has no orders)

4. REVIEW OF YOUR QUERY
SELECT customer_id, SUM(total) FROM orders;
Runs in SQLite: yes. It returns ONE row: SUM is 78.5 (all six orders), and customer_id comes from an arbitrary row because nothing tells SQLite how to group. PostgreSQL and SQL Server would reject this query with an error, which is useful: the database is warning you the question is not well formed.
Why it differs from your goal: you asked for one total per customer, but you did not say "per customer" in SQL.
Hint: which clause turns "per customer" into separate groups, and which column goes in it? Your result should have 3 rows: customer 1 with 36.5, customer 2 with 16.5, customer 3 with 25.5.

5. NEXT SESSION (30 minutes)
Concept: filtering groups with HAVING versus filtering rows with WHERE, and COUNT per group.
Warm-ups:
- How many orders did each customer place? (Ana 3, Ben 2, Cara 1)
- Which customers placed more than one order? (Ana, Ben)

Reviews (0)

Please login to leave a review.
Loading reviews...