Six topic areas. Every one tied to a real job outcome.
LearnQL covers 23 SQL skills — from SELECT basics and filtering to JOINs, window functions, CTEs, and advanced analytical patterns. Each skill has learn exercises, a no-hints test, and AI feedback that explains exactly what went wrong. Built for data analysts, engineers, and anyone preparing for a SQL interview.
Start free →The core of every SQL query — selecting columns, filtering rows, sorting results, and handling missing data.
SELECT Basics, Filtering, Sorting & Limits, NULL Handling
Read the reference →What you'll be able to answer
SELECT name, email, created_at FROM customers WHERE created_at >= NOW() - INTERVAL '30 days' ORDER BY created_at DESC;
SELECT name, category FROM products WHERE category IS NULL;
Summarizing data — counts, totals, averages — grouped by categories.
Aggregations, GROUP BY
Read the reference →What you'll be able to answer
SELECT category, SUM(price) AS total_revenue FROM orders GROUP BY category ORDER BY total_revenue DESC;
SELECT artist_id, COUNT(*) AS track_count FROM tracks GROUP BY artist_id HAVING COUNT(*) > 10;
Transforming raw data — cleaning text, working with dates, and categorizing values into meaningful labels.
String Functions, Pattern Matching, Date & Time, Date Arithmetic, CASE WHEN
Read the reference →What you'll be able to answer
SELECT DATE_TRUNC('month', created_at) AS month,
COUNT(*) AS signups
FROM users
GROUP BY 1
ORDER BY 1;SELECT order_id,
CASE
WHEN total > 500 THEN 'High'
WHEN total > 100 THEN 'Mid'
ELSE 'Low'
END AS value_tier
FROM orders;Combining data from multiple tables into a single result.
JOINs Core, JOINs Advanced, Multi-Table JOINs
Read the reference →What you'll be able to answer
SELECT c.name FROM customers c LEFT JOIN reviews r ON r.customer_id = c.id WHERE r.id IS NULL;
SELECT t.title, al.title AS album, ar.name AS artist FROM tracks t JOIN albums al ON al.id = t.album_id JOIN artists ar ON ar.id = al.artist_id;
Writing queries that reference other queries, and performing calculations across rows without collapsing them.
Subqueries, Correlated Subqueries, Window Functions, Advanced Windows
Read the reference →What you'll be able to answer
SELECT name, total_spent FROM customers WHERE total_spent > (SELECT AVG(total_spent) FROM customers);
SELECT artist, genre, streams,
RANK() OVER (PARTITION BY genre ORDER BY streams DESC) AS rank
FROM artist_stats;Writing complex, maintainable queries — breaking logic into reusable steps, combining result sets, and solving advanced analytical problems.
CTEs, Recursive CTEs, Set Operations, Analytical Patterns, Advanced Patterns
Read the reference →What you'll be able to answer
WITH q1_customers AS ( SELECT DISTINCT customer_id FROM orders WHERE order_date BETWEEN '2024-01-01' AND '2024-03-31' ), q2_customers AS ( SELECT DISTINCT customer_id FROM orders WHERE order_date BETWEEN '2024-04-01' AND '2024-06-30' ) SELECT * FROM q1_customers EXCEPT SELECT * FROM q2_customers;
SELECT track_id FROM top10_by_streams INTERSECT SELECT track_id FROM top10_by_revenue;