FROM en SQL: qué es, cómo se usa y ejemplos prácticos

En SQL, la cláusula FROM indica de qué tabla(s) o conjunto(s) de resultados se obtendrán los datos para una consulta. Es el punto de partida lógico del plan de ejecución: primero se construye el conjunto de filas base (tablas, vistas, subconsultas), luego se filtra (WHERE), se agrupa (GROUP BY), se filtra por agregados (HAVING), se proyecta (SELECT) y finalmente se ordena/limita (ORDER BY, LIMIT).

Aunque FROM parezca trivial, dominarlo es clave para escribir consultas claras, performantes y correctas, especialmente cuando hay múltiples tablas, subconsultas derivadas o funciones de ventana.

Sintaxis básica

SELECT columnas
FROM fuente
[WHERE ...]
[GROUP BY ...]
[HAVING ...]
[ORDER BY ...]
[LIMIT ...];

Donde fuente puede ser:

  • Una tabla o vista: FROM clientes
  • Varias tablas con JOIN: FROM clientes c JOIN pedidos p ON p.cliente_id = c.id
  • Una subconsulta (tabla derivada): FROM ( SELECT cliente_id, SUM(total) total FROM pedidos GROUP BY cliente_id ) t
  • Una CTE previa con WITH: WITH ventas AS (...) SELECT ... FROM ventas;
  • Funciones o tablas especiales según el motor (ej. generate_series() en PostgreSQL).

Ejemplos esenciales de FROM

1) Una sola tabla

SELECT id, nombre, email
FROM clientes;

2) Alias de tabla (recomendado)

SELECT c.id, c.nombre
FROM clientes AS c;

Usar alias corta la escritura y evita ambigüedades en joins.

3) INNER JOIN (coincidencias en ambas)

SELECT c.nombre, p.id, p.total
FROM clientes c
JOIN pedidos p ON p.cliente_id = c.id;

4) LEFT JOIN (todas las filas de la izquierda)

SELECT c.nombre, p.id AS pedido_id, p.total
FROM clientes c
LEFT JOIN pedidos p ON p.cliente_id = c.id;

Si un cliente no tiene pedidos, igual aparece con pedido_id = NULL.

5) FULL OUTER JOIN (si el motor lo soporta)

SELECT *
FROM a
FULL OUTER JOIN b ON a.id = b.id;

Devuelve coincidencias y no coincidencias de ambos lados.

6) CROSS JOIN (producto cartesiano)

SELECT a.x, b.y
FROM a
CROSS JOIN b;

Combina todas las filas de a con todas las de b. Úsalo con cuidado.

7) Subconsulta en FROM (tabla derivada)

SELECT t.cliente_id, t.total
FROM (
  SELECT cliente_id, SUM(total) AS total
  FROM pedidos
  GROUP BY cliente_id
) AS t
WHERE t.total > 1000;

Útil para encapsular cálculos y reutilizarlos.

8) FROM con CTE (WITH)

WITH ventas_por_cliente AS (
  SELECT cliente_id, SUM(total) total
  FROM pedidos
  GROUP BY cliente_id
)
SELECT c.nombre, v.total
FROM clientes c
JOIN ventas_por_cliente v ON v.cliente_id = c.id
WHERE v.total > 1000;

Más legible que una subconsulta anidada en FROM.

Orden lógico de evaluación (muy importante)

Aunque escribas SELECT ... FROM ... WHERE ..., el optimizador evalúa lógicamente así:

  1. FROM (+ JOIN): construye el conjunto base de filas.
  2. WHERE: filtra filas (antes de agregaciones).
  3. GROUP BY: agrupa.
  4. HAVING: filtra grupos.
  5. SELECT: proyecta columnas y expresiones.
  6. ORDER BY: ordena.
  7. LIMIT/OFFSET: limita.

Comprender esto evita errores como pretender usar un alias del SELECT en WHERE (todavía no existe ahí) y ayuda a empujar filtros lo antes posible.

Commas vs JOIN (no más coma-join)

SQL permite separar tablas por comas:

-- ❌ Evitar
SELECT c.nombre, p.total
FROM clientes c, pedidos p
WHERE p.cliente_id = c.id;

Funciona, pero es menos claro y propenso a olvidos. Preferí la sintaxis explícita:

-- ✅ Recomendado
SELECT c.nombre, p.total
FROM clientes c
JOIN pedidos p ON p.cliente_id = c.id;

FROM con vistas y tablas temporales

  • Vistas: FROM ventas_mensuales (encapsulan una consulta compleja).
  • Tablas temporales (según motor): CREATE TEMP TABLE ... y luego FROM temp_tabla durante la sesión.
  • Materialized views (si existen): permiten FROM sobre vistas precalculadas para mejorar performance.

FROM y funciones/tablas especiales (según SGBD)

  • PostgreSQL: FROM generate_series(...), LATERAL (ver más abajo).
  • Oracle: FROM DUAL para seleccionar constantes: SELECT 1 AS uno FROM DUAL;
  • SQL Server: FROM (VALUES (...), (...)) AS v(col1,col2) para construir filas literales.
  • MySQL: a veces permite omitir FROM al seleccionar constantes: SELECT 1;

LATERAL / APPLY: cuando la subconsulta depende de cada fila (avanzado)

En PostgreSQL, LATERAL permite que la subconsulta en FROM use columnas de la tabla previa:

SELECT c.id, x.top_pedido
FROM clientes c
CROSS JOIN LATERAL (
  SELECT p.total AS top_pedido
  FROM pedidos p
  WHERE p.cliente_id = c.id
  ORDER BY p.total DESC
  LIMIT 1
) x;

En SQL Server, el patrón equivalente se hace con CROSS/OUTER APPLY.

Buenas prácticas con FROM

  1. Alias claros: c para clientes, p para pedidos. Evitá nombres crípticos.
  2. JOINs explícitos: hacen obvias las relaciones y evitan productos cartesianos accidentales.
  3. Filtrar temprano: empujá condiciones a ON/WHERE para reducir filas cuanto antes.
  4. Seleccionar solo lo necesario: evitá SELECT * en tablas grandes o tablas derivadas; mejora I/O y legibilidad.
  5. Indexar claves de join: índices sobre p.cliente_id, c.id, etc., aceleran el plan de FROM.
  6. Prefiere CTE para claridad (o subconsulta en FROM) cuando el cálculo intermedio mejora la lectura.
  7. Nombrar columnas en tablas derivadas (algunos motores lo exigen).
  8. Verificar collation/tipos compatibles cuando unís texto entre tablas distintas.

Errores comunes (y cómo evitarlos)

  1. Olvidar la condición de JOIN
SELECT *
FROM clientes c
JOIN pedidos p;  -- ❌ Falta ON → producto cartesiano gigantesco

Solución: agregá ON p.cliente_id = c.id o el USING(...) correspondiente.

  1. Ambigüedad de columnas
SELECT id  -- ❌ ¿de qué tabla?
FROM clientes c JOIN pedidos p ON p.cliente_id = c.id;

Solución: calificá: c.id o p.id.

  1. Usar alias del SELECT dentro de WHERE
    Recordá el orden lógico: el alias no existe aún. Usá la expresión original o envolvé en una subconsulta/CTE.
  2. Tabla derivada sin alias
SELECT *
FROM (SELECT ...)  -- ❌ algunos motores exigen alias

Solución: FROM (SELECT ...) AS t.

  1. FULL OUTER JOIN no soportado
    MySQL no lo soporta directamente. Alternativas: LEFT JOIN ... UNION ... RIGHT JOIN (con cuidado).
  2. JOIN condición en WHERE (con LEFT)
    Poner filtros de la tabla derecha en WHERE puede convertir un LEFT JOIN en INNER sin querer:
-- ❌ Esto elimina filas sin match
FROM c LEFT JOIN p ON p.cliente_id = c.id
WHERE p.total > 0;

Solución: mover el filtro al ON o usar WHERE (p.total > 0 OR p.total IS NULL) según el objetivo.

Ejemplos prácticos más completos

Ventas por cliente con filtro de periodo

WITH ventas AS (
  SELECT cliente_id, SUM(total) total
  FROM pedidos
  WHERE fecha BETWEEN '2025-01-01' AND '2025-06-30'
  GROUP BY cliente_id
)
SELECT c.nombre, v.total
FROM clientes c
JOIN ventas v ON v.cliente_id = c.id
ORDER BY v.total DESC
LIMIT 10;

Productos sin ventas (anti-join)

SELECT pr.id, pr.nombre
FROM productos pr
LEFT JOIN pedidos_det pd ON pd.producto_id = pr.id
WHERE pd.producto_id IS NULL;

Top pedido por cliente (LATERAL / APPLY-style)

SELECT c.id, c.nombre, x.max_total
FROM clientes c
CROSS JOIN LATERAL (
  SELECT MAX(p.total) AS max_total
  FROM pedidos p
  WHERE p.cliente_id = c.id
) x;

Preguntas frecuentes (FAQ)

1) ¿Puedo usar varias fuentes en FROM sin JOIN?
Se puede con comas, pero no es recomendable. Usá JOIN explícito para evitar errores y ser más claro.

2) ¿Qué diferencia hay entre subconsulta en FROM y CTE (WITH)?
Funcionalmente parecidas; la CTE suele ser más legible y reutilizable, y en algunos motores puede materializarse (o no). Elegí la que haga el código más claro y performante.

3) ¿Por qué mi LEFT JOIN “pierde” filas?
Probablemente pusiste filtros de la tabla derecha en WHERE en vez de ON. Eso transforma el LEFT en INNER. Ajustá la condición.

*4) ¿Es malo usar SELECT ?
No es “malo”, pero en producción conviene seleccionar solo lo necesario para reducir transferencia y acoplamiento.

5) ¿FROM siempre necesita una tabla real?
No. Podés usar vistas, CTE, tablas derivadas o incluso funciones/tablas especiales del motor (ej. DUAL en Oracle, VALUES en SQL Server).

Conclusión

FROM es la base de toda consulta SQL: define de dónde salen las filas que vas a transformar y presentar. Dominarlo implica saber elegir la fuente adecuada (tabla, vista, subconsulta, CTE), unir correctamente varias tablas con JOIN, y estructurar el plan de ejecución para filtrar lo antes posible y devolver solo lo necesario.

Con buenas prácticas (alias claros, joins explícitos, índices en claves de unión, filtros bien ubicados) tus consultas serán más legibles, correctas y rápidas.

Domina la selección de tablas en SELECT y FROM y vuelve al Glosario SQL completo.

Scroll al inicio