The Data Foundry
Built by Data with Pranjal
All Practice
Choose a guided lab or practice track
SQL Lab
Interview SQL with real data and validation
Python Lab
Data engineering Python practice
PySpark Lab
Spark code review and production fixes
Airflow Lab
DAG incidents, retries, sensors, and backfills
AWS Lab
Service choices, architecture, security, and cost
System Design Studio
Architecture trade-offs and interview framing
The Data Foundry is improving every week. If something feels unclear, broken, or missing, tell us and we will use it to improve the platform.
Inspect the data, write the solution, run validation checks, and explain the production lesson.
Labs
294
In progress
0
Done
Free
80
Choose a question first
Open any SQL question from the library. Once you choose one, the question navigator stays on the left so moving to the next lab is quick.
Solve this SQL interview task using the seeded tables: Second Highest Salary. Your solution should work for the visible sample data and for hidden edge-case datasets that test ties, NULLs, duplicate rows, missing keys, and boundary conditions where relevant.
Return the third highest distinct salary from employees. Your solution should work for the visible sample data and for hidden edge-case datasets that test ties, NULLs, duplicate rows, missing keys, and boundary conditions where relevant.
Return employees in the top three distinct salary bands inside each department. Ranking must restart per department, and employees tied at a qualifying salary must all remain in the output.
Solve this SQL interview task using the seeded tables: Latest Order per Customer. Your solution should work for the visible sample data and for hidden edge-case datasets that test ties, NULLs, duplicate rows, missing keys, and boundary conditions where relevant.
Solve this SQL interview task using the seeded tables: First and Last Order per Customer. Your solution should work for the visible sample data and for hidden edge-case datasets that test ties, NULLs, duplicate rows, missing keys, and boundary conditions where relevant.
First aggregate all sales to one row per sale_date, then calculate cumulative revenue in ascending date order.
Solve this SQL interview task using the seeded tables: 3-Day Moving Average. Your solution should work for the visible sample data and for hidden edge-case datasets that test ties, NULLs, duplicate rows, missing keys, and boundary conditions where relevant.
Aggregate sales to one row per calendar month, then subtract the previous available month’s revenue using LAG. The first available month should have a NULL delta.
Solve this SQL interview task using the seeded tables: Rank Cities by Sales with Ties. Your solution should work for the visible sample data and for hidden edge-case datasets that test ties, NULLs, duplicate rows, missing keys, and boundary conditions where relevant.
Solve this SQL interview task using the seeded tables: Top 10 Percent of Customers by Spend. Your solution should work for the visible sample data and for hidden edge-case datasets that test ties, NULLs, duplicate rows, missing keys, and boundary conditions where relevant.
Solve this SQL interview task using the seeded tables: Customers with No Orders. Your solution should work for the visible sample data and for hidden edge-case datasets that test ties, NULLs, duplicate rows, missing keys, and boundary conditions where relevant.
Solve this SQL interview task using the seeded tables: Employees Earning Above Department Average. Your solution should work for the visible sample data and for hidden edge-case datasets that test ties, NULLs, duplicate rows, missing keys, and boundary conditions where relevant.
Return all customers with their profile city when available. Customers without a profile should still appear with NULL city. The important part is coverage: the output must preserve every base customer row even when enrichment data is missing. This is a common production issue when optional dimension/profile tables arrive late.
Return the employees in the top two salary bands per department. If multiple employees share the same salary band, include all of them. The important part is ranking inside each group, not globally. A query that uses a global LIMIT may look correct on tiny data but fails as soon as each department needs its own leaderboard.
Aggregate bin-level inventory for the latest snapshot date and return positive stock only. The important part is matching the output grain to the report grain. Bin-level or event-level input often needs to be aggregated before it becomes a warehouse mart.
Find duplicated email addresses after normalizing email casing. Ignore rows where email is NULL. The important part is normalization before grouping. Production duplicates often hide behind casing, whitespace, or NULL values, so the query must count the same key the business system treats as identical.
Find customers who do not have any completed order. The query should be safe even when the orders table contains NULL customer_id values. The important part is NULL-safe exclusion. In production pipelines, failed events and guest checkouts often create NULL foreign keys that can break NOT IN logic.
Return dates where the warehouse temperature is higher than the previous day in the sample feed. The important part is comparing a row with the previous row in time order. A static threshold is not enough when the business asks for day-over-day movement.
Calculate the percentage of delivery records where order_date equals delivered_date. The important part is building the exact SLA numerator and denominator. Counting rows alone is not a rate, and date equality must be checked per delivery.
Find users who had at least one event exactly one day after their first recorded event date. The important part is measuring activity relative to each user's first event date. Multiple events per day should not change the user-level retention answer.
Calculate click-through rate percentage per ad as clicks divided by impressions. Avoid divide-by-zero failures. The important part is conditional counting. The metric should divide clicks by impressions, not by all events, and should avoid divide-by-zero failures.
Calculate completed-order revenue per product and category from order_items joined to products and orders. The important part is filtering to valid revenue before aggregation. Cancelled or non-completed orders can inflate downstream marts if the status filter is missed.
Compute net balance change per account and return only accounts above 10000. The important part is financial sign handling. Credits and debits move balances in opposite directions, so a plain SUM(amount) can produce a dangerously wrong report.
Return countries that qualify as large markets by population or area. The important part is translating the business rule exactly. When the rule says either threshold qualifies, using AND silently removes valid records.
Find classes with at least five distinct enrolled students. The important part is counting unique students, not enrollment events. Retry events or duplicate rows should not inflate class capacity numbers.