Why testers need SQL
The UI shows what the application chooses to show. The database shows what actually happened. Testers use SQL to confirm that an order was written with the right total, to find customers created twice by a double-click, to spot order items whose order was deleted, and to mine test-run history for flaky tests. Most SDET interview loops include at least one query, and the questions are usually these practical checks rather than textbook exercises.
The lab uses two databases: a small shop (customers, products, orders, order items, payments) and a test-results database (builds, test runs, defects). Every challenge is a task you might do in a real sprint.
A suggested order
- Basics and NULL traps: customers with no city, where
WHERE city = NULLreturns nothing andWHERE city IS NULLis correct, then failures per test, the second-highest price and duplicate emails withGROUP BY … HAVING COUNT(*) > 1. - Joins and integrity: customers without orders and orphan order items both use the anti-join pattern
LEFT JOIN … WHERE right.id IS NULL, the single most useful query for finding data bugs. - Test analytics: pass rate on the latest build, detecting flaky tests, time to close defects and deleting feature-branch builds safely.
- Advanced: payment reconciliation, top customer per city with window functions, and duration regressions between builds.
How queries are checked
Your SQL runs on SQLite compiled to WebAssembly, in a Web Worker in your browser, on a fresh in-memory database for every check. The result set is compared with the reference solution: same columns in the same order and the same rows, in order only when the task asks for ORDER BY. Extra checks then alter the data, for example by adding a second duplicate or a NULL, and run your query again. A query that hard-codes the expected ids passes the first check and fails the rest, which is the point: a data check that only works on today's data is not a check.
SQLite is close to standard SQL for everything here (joins, CTEs, window functions), but date functions differ between databases. The challenges note this where it matters, so you can translate to PostgreSQL or MySQL in an interview.
Common mistakes
- Comparing with
= NULLor<> NULL. Any comparison with NULL is unknown, so the row is filtered out. - Joining a one-to-many table and then summing, which counts the parent value once per child row. Aggregate the child table first, then join.
- Using
COUNT(column)when you meantCOUNT(*): the first skips NULLs. - Writing a DELETE without first running the same WHERE clause as a SELECT.
Frequently asked questions
Which SQL dialect does the lab use?
SQLite, running in your browser through WebAssembly. Joins, aggregates, CTEs and window functions behave as in PostgreSQL and MySQL; date functions are the main difference.
Why did my query pass the sample data but fail another check?
Later checks change the data, for example by adding a NULL or another duplicate. Your query probably relies on something true only for the sample rows, such as a specific id or a single match.
What SQL do QA engineers need for interviews?
SELECT with WHERE, NULL handling, joins (especially LEFT JOIN for finding missing rows), GROUP BY with HAVING, subqueries or CTEs, and for senior roles window functions such as ROW_NUMBER.
Is any data sent to a server?
No. The database and your queries stay in your browser.