Español

For teachers

Caso Abierto for the classroom

A detective game solved by writing real SQL against a real database, not by picking multiple-choice answers.

What it is

Every case in Caso Abierto is a database. The student writes real SQL, using DuckDB, which follows the SQL standard for the basics.

To close a case they submit the query that proves their answer, and the game rejects it if it only states the answer instead of proving it with data.

The 28 cases

Four seasons. The table comes from the same catalog the game uses. The "trap" column links to the page that explains, with real SQL, the mistake that case is built to catch.

Season 1: Lumen Bay
No.CaseDifficultyTechniquesTrap
0The First Query◆◇◇◇◇SELECT, WHERE, a time condition
1The File Nobody Asked For◆◇◇◇◇SELECT, WHERE, date ranges, ORDER BYWhy does BETWEEN eat the last day of the range?
2The Witness's Description◆◇◇◇◇compound WHERE, LIKE, IN, BOOLEAN, NULL
3The 23:40 Call◆◆◇◇◇JOIN, table aliases, chaining two joins
4The Regular◆◆◇◇◇GROUP BY, COUNT, HAVING, filtering before and after groupingWhy doesn't WHERE find the customer who 'always' pays cash?
5Eleven Alibis and One That Isn't◆◆◆◇◇LEFT JOIN, NOT EXISTS, anti-join, interval overlapWhen do two time intervals actually overlap?
6Private Room 3◆◆◆◇◇self-join, WITH (CTE), interval overlap, excluding yourselfWhy does a self-join always bring back one extra row?
7The Card That Was in Two Places◆◆◆◆◇window functions, LAG, PARTITION BY, QUALIFY, date_diffWhy does the running balance repeat the exact same number on two different rows? · Why can't WHERE filter on a window function's result?
8What the Anacleta Brought◆◆◆◆◆chained CTEs, multiple JOINs, overlap, date arithmetic, reasoning in steps
Season 2: The Desk
No.CaseDifficultyTechniquesTrap
1The Account That's Bleeding◆◆◇◇◇SUM, GROUP BY, cost arithmetic, ORDER BY
2Trading Against the Mirror◆◆◆◇◇joining one table by two keys, comparing both sides of the same row, GROUP BY
3The Entry Nobody Wrote◆◆◆◇◇anti-join, NOT EXISTS, LEFT JOIN ... IS NULL, the NOT IN with NULL trapWhy does NOT IN return zero rows?
4The Collector That Got Stuck◆◆◆◇◇LAG, gaps and islands, row_number, streak detection, data quality
5The One Who Knew◆◆◆◆◇interval join, ASOF JOIN, hit rate, sample sizeA rate needs a denominator
6The Decoy◆◆◆◆◇FILTER, conditional ratios, percentiles, combining several conditions
7The Toll◆◆◆◆◆date_part, hourly cohorts, theoretical vs. actual, decomposing a result, basis points
8Follow the Money◆◆◆◆◆WITH RECURSIVE, graphs in SQL, cycle control, terminal account
Season 3: The Basement
No.CaseDifficultyTechniquesTrap
1The Report That Multiplied Itself◆◆◆◇◇cardinality, fan-out, aggregate before joining, COUNT DISTINCTThe join that multiplies rows
2The Double◆◆◆◇◇deduplication, row_number, QUALIFY, business key vs. row
3Yesterday's Rate◆◆◆◆◇tables with history, temporal join, valid_from / valid_to, recompute and compare
4The Mute Unit◆◆◆◆◇normalizing units, currency conversion, reading the data dictionary, CASE
5The Twenty-Five-Hour Day◆◆◆◆◇time zones, AT TIME ZONE, date_trunc, defining the day before groupingTime zones: store UTC, show local
6The Ones Who Aren't There Anymore◆◆◆◆◆survivorship bias, historical universe, join with validity, average of averagesSurvivorship bias lives in the JOIN
Season 4: File 88-C
No.CaseDifficultyTechniquesTrap
1The Night in March◆◆◆◆◇time windows, JOIN between tables without a key, subquery as a reference, strftime
2The Cash◆◆◆◆◆JOIN by amount and date window, INTERVAL, GROUP BY with HAVING, chain: till → carrier → account
4The Weight of the Anacleta◆◆◆◆◆JOIN by date with tolerance, aggregation by port call, HAVING against a subquery, several chained CTEs
5The Cards◆◆◆◆◆LAG window function, temporal self-join, date_diff, JOIN by date with tolerance
8File 88-C◆◆◆◆◆several CTEs in one query, conditional aggregates, HAVING against a subquery, one row with the whole truth

How it works in class

The teacher asks for a group code and gets a link. That link opens the full game in each student's browser: no accounts, nothing to install, works on the school lab computers.

Each student's progress is saved only in that browser. If a student switches computers, they can copy their progress as text from Settings → Progress ("Copy" button) and paste it on the other computer ("Paste…" button); the game merges it with whatever was already there, keeping whichever case is further along.

Privacy

The classroom version, the game that opens from the group code link, has no accounts, asks the student for no data, has no ads and carries no analytics.

This public page you're reading is different: it counts visits with Cloudflare Web Analytics, with no cookies.

What we don't promise

We don't measure how long a student takes or how much they learn, not yet. Cases 0 through 4 are short. Difficulty 4 and 5 cases can take a full class session. Not measured yet.

How to request a license

Write from your institutional email with the course, the institution, the approximate number of students and the semester dates.

Write to christianvadillo@hotmail.com. Free for the classroom.

50-minute class guide

A complete lesson plan, with three levels and discussion questions. Printable. 50-minute class guide →

The 15 traps

The mistakes hidden in the cases, each on its own page: what breaks, a minimal SQL example that reproduces it, the corrected version and why.

The first case runs free in your browser, no signup.

Play the first case free →