Vamos a meternos aún más en la madriguera del conejo: veamos cómo usar subconsultas en la cláusula FROM. Es uno de los trucos favoritos de los desarrolladores de SQL porque te permite crear tablas temporales potentes justo "en el momento" y reutilizarlas como si existieran en la base de datos.
Imagina que tienes que hacer un informe que requiere cálculos, agrupaciones o filtrado de datos, pero no quieres crear tablas temporales adicionales en el servidor. ¿Qué hacer? Aquí es donde las subconsultas en FROM te salvan la vida. Te permiten:
- Unir datos temporalmente o agregarlos antes de la consulta principal.
- Crear conjuntos de datos estructurados "al vuelo".
- Reducir el número de operaciones, pidiendo a la base de datos que guarde la mínima cantidad de datos intermedios.
Las subconsultas en FROM funcionan como mini-tablas que puedes usar en tu consulta principal. Es como construir con piezas de Lego: rápido, flexible y sin complicaciones extras :)
Bases de las subconsultas en FROM
En las subconsultas en FROM usamos subconsultas para crear una tabla temporal (o subtabla) que se convierte en parte de la consulta general. Para esto hay que hacer tres pasos clave:
- Escribir la subconsulta en la cláusula
FROMentre paréntesis. - Asignar un alias (seudónimo) a la subconsulta.
- Usar ese alias como si fuera una tabla real.
Sintaxis
SELECT columnas
FROM (
SELECT columnas
FROM tabla
WHERE condición
) AS alias
WHERE condición_externa;
¿Suena un poco intimidante? Vamos a ver ejemplos.
Ejemplo: Estudiantes y nota media
Supón que tenemos dos tablas:
students (datos de estudiantes — su nombre e ID):
| student_id | student_name |
|---|---|
| 1 | Alex |
| 2 | Anna |
| 3 | Dan |
grades (datos de notas de los estudiantes):
| grade_id | student_id | grade |
|---|---|---|
| 1 | 1 | 80 |
| 2 | 1 | 85 |
| 3 | 2 | 90 |
| 4 | 3 | 70 |
| 5 | 3 | 75 |
Ahora el reto: obtener la lista de estudiantes y su nota media.
Podemos empezar con una subconsulta sencilla que calcule la nota media de cada estudiante y luego usarla en la consulta principal.
SELECT s.student_name, g.avg_grade
FROM (
SELECT student_id, AVG(grade) AS avg_grade
FROM grades
GROUP BY student_id
) AS g
JOIN students AS s ON s.student_id = g.student_id;
Resultado:
| student_name | avg_grade |
|---|---|
| Alex | 82.5 |
| Anna | 90.0 |
| Dan | 72.5 |
Tablas temporales "al vuelo"
Las subconsultas en FROM son especialmente útiles cuando necesitas hacer más de un nivel de procesamiento de datos. Por ejemplo, si quieres no solo obtener la nota media, sino también calcular la nota máxima de cada estudiante — todo en una sola consulta.
SELECT g.student_id, g.avg_grade, g.max_grade
FROM (
SELECT student_id,
AVG(grade) AS avg_grade,
MAX(grade) AS max_grade
FROM grades
GROUP BY student_id
) AS g;
Resultado:
| student_id | avg_grade | max_grade |
|---|---|---|
| 1 | 82.5 | 85 |
| 2 | 90 | 90 |
| 3 | 72.5 | 75 |
Fíjate que esto funciona como una tabla temporal real con sus propias columnas: avg_grade y max_grade.
¿Cuándo es mejor usar subconsultas en FROM?
Para datos agregados. Si quieres primero hacer cálculos (como medias, sumas o máximos) y luego unir los resultados con otras tablas.
Para filtrar datos. Cuando necesitas filtrar datos antes de unirlos con la tabla principal.
Para simplificar consultas complejas. Dividir tareas complicadas en pasos ayuda a no liarte.
Ejemplo: Informe de estudiantes con dos niveles de procesamiento
Imagina que queremos encontrar estudiantes cuya nota media sea mayor que 80. Empezamos con una subconsulta que calcula las medias y luego la usamos en el filtro.
SELECT s.student_name, g.avg_grade
FROM students AS s
JOIN (
SELECT student_id, AVG(grade) AS avg_grade
FROM grades
GROUP BY student_id
) AS g ON s.student_id = g.student_id
WHERE g.avg_grade > 80;
Resultado:
| student_name | avg_grade |
|---|---|
| Alex | 82.5 |
| Anna | 90.0 |
Detalles y recomendaciones
Alias obligatorio. Siempre pon un alias a la subconsulta (por ejemplo, AS g), si no, PostgreSQL no sabrá cómo referirse a esa "tabla temporal".
Optimización. Las subconsultas en FROM pueden ser más lentas que los JOIN normales, sobre todo si filtras datos dentro de la subconsulta.
Indexación. Asegúrate de que los campos que usas para unir, los índices y los filtros estén optimizados — esto afecta mucho al rendimiento.
Ejemplo de consulta compleja: cursos y número de estudiantes
Ahora vamos con un reto más real. Imagina que tenemos esta tabla:
courses (lista de cursos):
| course_id | course_name |
|---|---|
| 1 | SQL Basics |
| 2 | Python Basics |
Y enrollments (inscripciones de estudiantes en cursos):
| student_id | course_id |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
Ahora queremos saber cuántos estudiantes están inscritos en cada curso.
SELECT c.course_name, e.students_count
FROM courses AS c
JOIN (
SELECT course_id, COUNT(student_id) AS students_count
FROM enrollments
GROUP BY course_id
) AS e ON c.course_id = e.course_id;
Resultado:
| course_name | students_count |
|---|---|
| SQL Basics | 2 |
| Python Basics | 1 |
Espero que te haya molado la lección... pero la siguiente será aún más interesante :)
GO TO FULL VERSION