Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SQL traps

Fifteen SQL mistakes that don't throw an error. The query runs, returns something that looks reasonable, and it's wrong.

Each one comes with the query that has the trap, the fix, why it happens, and a minimal dataset. verify.py runs all of them in DuckDB and checks that the broken query and the fixed one really give different results, in the way the page says. Nothing here is just asserted.

In English and in Spanish.

Trap
The join that multiplies rows
A rate needs a denominator
A WHERE on the right-hand table turns your LEFT JOIN back into an INNER JOIN
Survivorship bias lives in the JOIN
Time zones: store UTC, show local
Why does NOT IN return zero rows?
Why does COUNT(column) give a smaller number than COUNT(*)?
Why doesn't LIKE find a name that's right there in the table?
Why does the biggest transfer of the month show up as $990?
Why does BETWEEN eat the last day of the range?
Why does a self-join always bring back one extra row?
When do two time intervals actually overlap?
Why does the running balance repeat the exact same number on two different rows?
Why can't WHERE filter on a window function's result?
Why doesn't WHERE find the customer who 'always' pays cash?

Run the checks

pip install duckdb
python verify.py            # all of them
python verify.py fanout     # just one

The SQL is DuckDB. Almost all of it is plain standard SQL; where an engine behaves differently (for example, DuckDB's / never does integer division) the page says so.

Where these come from

They are the traps hidden in the case files of Caso Abierto, a detective game where you solve each case by writing SQL and have to hand in the query that proves your accusation. The first case plays free in the browser.


Trampas de SQL

Quince errores de SQL que no dan error. La consulta corre, devuelve algo razonable y está mal.

Cada una trae la consulta con la trampa, la corrección, por qué pasa y un dataset mínimo. verify.py las ejecuta todas en DuckDB y comprueba que la consulta rota y la corregida dan resultados distintos, en el sentido que explica cada página.

Trampa
El join que multiplica filas
Una tasa sin denominador no significa nada
Un WHERE sobre la tabla derecha convierte tu LEFT JOIN en INNER
El sesgo de supervivencia está en el JOIN
Zonas horarias: guarda UTC, muestra local
¿Por qué NOT IN devuelve cero filas?
¿Por qué COUNT(columna) da menos que COUNT(*)?
¿Por qué LIKE no encuentra un nombre que sí está en la tabla?
¿Por qué la transferencia más grande del mes sale como $990?
¿Por qué BETWEEN se come el último día del rango?
¿Por qué un self-join siempre trae una fila de más?
¿Cuándo se solapan de verdad dos intervalos de tiempo?
¿Por qué el saldo acumulado repite el mismo número en dos filas distintas?
¿Por qué WHERE no puede filtrar el resultado de una window function?
¿Por qué el WHERE no encuentra a quien 'siempre' paga en efectivo?

Salen de los casos de Caso Abierto, un juego de detectives que se resuelve escribiendo SQL. El primer caso se juega gratis en el navegador.

License

Text: CC BY 4.0. Code (verify.py): MIT.

About

15 SQL mistakes that return wrong results without an error. Each with a minimal dataset and a DuckDB check. English and Spanish.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages