Un JOIN une dos tablas en una sola consulta
Las bases de datos relacionales reparten los datos en varias tablas a propósito: los clientes en una tabla, los pedidos en otra y los productos en una tercera. Así, cada dato vive en un único sitio. El problema aparece cuando quieres responder una pregunta real ("¿qué clientes pidieron qué productos?"): necesitas volver a juntar las piezas. Para eso sirve un JOIN.
El INNER JOIN es el más usado de todos. Empareja filas de dos tablas siempre que se cumpla una condición, y descarta lo demás.
Tres clientes, tres pedidos, pero Chen no tiene pedidos, así que Chen no aparece. Esa es la esencia del inner: solo sobreviven las filas que tienen pareja.
El modelo mental: emparejar filas y luego filtrar
Un INNER JOIN se lee así: agarra cada fila de la primera tabla, recórrela contra cada fila de la segunda y quédate con el par únicamente cuando la condición del ON se cumpla. Conceptualmente es un producto cartesiano gigante seguido de un filtro. SQLite no lo ejecuta así realmente (tira de índices cuando puede), pero el modelo sirve para predecir qué resultado vas a obtener.
Algunos hábitos que vale la pena adoptar desde ya:
- Usa alias para las tablas (
customers AS c) cuando vayas a mencionarlas más de una vez. Reduce el ruido visual. - Cualifica las columnas (
c.name,o.total) cuando ambas tablas podrían tenerlas. - El orden en
ON o.customer_id = c.idno importa:c.id = o.customer_idfunciona exactamente igual.
INNER JOIN vs JOIN: ¿hay diferencia?
En SQLite (y en SQL estándar), un JOIN a secas equivale a un INNER JOIN. La palabra clave INNER es opcional.
Ambos estilos generan el mismo plan de ejecución y devuelven las mismas filas. Escribir INNER JOIN de forma explícita aporta una pequeña mejora de legibilidad cuando mezclas distintos tipos de join: deja clarísima la intención al lado de un LEFT JOIN que aparezca unas líneas más abajo.
ON vs USING
Cuando las columnas del join se llaman igual en ambas tablas, USING (columna) es más corto que ON a.col = b.col:
USING (customer_id) hace dos cosas: empareja las filas donde customer_id coincide y, además, fusiona la columna para que aparezca una sola vez en el resultado. Úsalo cuando ambas tablas realmente comparten el mismo nombre de columna. Si los nombres difieren (orders.customer_id = customers.id) o la condición va más allá de una simple igualdad, quédate con ON.
INNER JOIN con 3 tablas en SQLite
Para unir varias tablas en SQLite, encadena los JOIN añadiendo más cláusulas JOIN ... ON .... Cada nueva cláusula conecta el resultado acumulado con otra tabla.
Léelo de arriba abajo: los clientes se conectan con los pedidos, y los pedidos con los artículos. Cada fila del resultado representa una combinación cliente–pedido–artículo. Si falta una coincidencia en cualquier punto de la cadena, esa fila se descarta: es la regla del INNER JOIN aplicada en cada paso.
Filtrar con WHERE
ON define cómo emparejar las filas. WHERE filtra el resultado ya emparejado. En el caso concreto de los INNER JOIN, da igual si pones una condición extra en ON o en WHERE: el resultado son las mismas filas. Aun así, la convención es clara: las condiciones de unión van en ON y los filtros de filas van en WHERE.
Esto se lee como "une customers con orders y, después, quédate solo con los clientes del Reino Unido cuyo pedido supere 20". Dos roles, dos cláusulas: tu yo del futuro te lo agradecerá. (Cuando empieces a escribir LEFT JOINs, la diferencia entre ON y WHERE deja de ser cosmética, pero eso lo vemos en la siguiente página.)
Varias condiciones en ON
La cláusula ON admite cualquier expresión booleana, no solo una igualdad. Resulta muy útil cuando la relación entre las tablas abarca más de una columna, o cuando quieres filtrar el lado derecho ya en el momento del join.
El pedido cancelado desaparece porque la segunda condición no se cumple. En un inner join podrías escribir perfectamente WHERE o.status = 'paid' y obtener el mismo resultado. La ventaja de usar ON es que mantiene la lógica de "qué cuenta como coincidencia" pegada al join.
Errores comunes al usar INNER JOIN
Hay varias cosas que suelen hacer tropezar:
- Olvidar la cláusula
ON. En SQLite,FROM a INNER JOIN bsinONes un error de sintaxis. (Una simple coma —FROM a, b— sí compila, pero te da un cross join, que casi nunca es lo que buscabas.) - Duplicados inesperados. Si un cliente tiene tres pedidos, su nombre aparecerá tres veces en el resultado. Eso es comportamiento normal del join, no un bug. Si quieres una fila por cliente, agrupa con
GROUP BY. - Filas que faltan. Si esperabas ver a un cliente y no aparece, es porque la condición del join no coincidió: revisa si hay
NULLen las columnas del join, o pásate aLEFT JOIN. - Nombres de columna ambiguos.
SELECT id FROM customers JOIN orders ON ...falla porque ambas tablas tienenid. Hay que cualificarlo:c.idoo.id.
Lo que viene: LEFT JOIN
INNER JOIN funciona genial cuando "no hay coincidencia" significa "descarta esta fila". Pero a veces quieres listar a todos los clientes, incluidos los que no tienen pedidos, dejando NULL donde faltan datos. Para eso está LEFT JOIN, que veremos a continuación.
Preguntas frecuentes
¿Qué hace INNER JOIN en SQLite?
INNER JOIN devuelve solo las filas que tienen coincidencia en ambas tablas según la condición del ON. Las filas que no casan en alguno de los dos lados se descartan. Es el join por defecto: en SQLite, escribir JOIN o INNER JOIN es exactamente lo mismo.
¿Cuál es la diferencia entre INNER JOIN y LEFT JOIN en SQLite?
INNER JOIN se queda solo con las filas emparejadas. LEFT JOIN, en cambio, conserva todas las filas de la tabla izquierda y rellena con NULL los campos de la derecha cuando no hay coincidencia. Usa INNER JOIN cuando una falta de match signifique 'descarta esta fila' y LEFT JOIN cuando signifique 'muéstrala igualmente'.
¿Se pueden unir tres tablas con INNER JOIN en SQLite?
Sí, basta con encadenar otra cláusula JOIN ... ON .... Cada join enlaza el resultado acumulado con una nueva tabla. No hay un límite duro, pero a partir de cuatro o cinco tablas la consulta se vuelve difícil de leer y suele compensar usar una CTE.
¿Cuándo conviene usar USING en lugar de ON?
USING (columna) es un atajo cuando la columna de unión se llama igual en ambas tablas. Queda más corto y, además, fusiona la columna duplicada en una sola en el resultado. Si los nombres no coinciden o necesitas una condición más compleja, recurre a ON.