Aprende SQL

El orden de ejecución en SQL

Lección 04 · Agregación y ejecución

El orden de ejecución en SQL

Aunque escribimos las consultas SQL en un orden determinado, el motor de base de datos las ejecuta en un orden diferente. Entender esto es clave para escribir consultas correctas y eficientes.

✍️ Lo que escribes
1. FROM
2. WHERE
3. GROUP BY
4. HAVING
5. SELECT
6. ORDER BY
7. LIMIT
⚡ Cómo se ejecuta
1º. SELECT
2º. FROM
3º. WHERE
4º. GROUP BY
5º. HAVING
6º. ORDER BY
7º. LIMIT

Orden de escritura vs. orden de ejecución

Paso Lo que escribes Cuándo se ejecuta
1 SELECT
2 FROM
3 WHERE
4 GROUP BY
5 HAVING
6 ORDER BY
7 LIMIT

¿Por qué importa?

El orden de ejecución explica por qué:

  1. No puedes usar alias del SELECT en WHERE: WHERE se ejecuta antes que SELECT.
  2. Puedes usar alias del SELECT en ORDER BY: ORDER BY se ejecuta después de SELECT.
  3. HAVING filtra grupos, no filas: HAVING se ejecuta después de GROUP BY.

Flujo de ejecución

SELECT developer, COUNT(*) AS total    -- 5. Selecciona columnas
FROM videogames                         -- 1. Accede a la tabla
WHERE year > 2000                       -- 2. Filtra filas
GROUP BY developer                      -- 3. Agrupa
HAVING COUNT(*) > 1                     -- 4. Filtra grupos
ORDER BY total DESC                     -- 6. Ordena resultado
LIMIT 5;                                -- 7. Limita filas devueltas

LIMIT siempre se ejecuta al final, después de ordenar. Esto garantiza que obtienes los primeros N resultados ya ordenados.

Errores comunes por el orden de ejecución

Conocer el orden de ejecución te ayuda a evitar errores muy frecuentes:

1. No puedes usar un alias del SELECT en WHERE

-- ❌ Esto da error en PostgreSQL, MySQL y SQL Server:
--    'total' no existe aún cuando se ejecuta WHERE.
--    En este playground (SQLite) puede funcionar, pero no es SQL estándar.
SELECT developer, COUNT(*) AS total
FROM videogames
WHERE total > 1
GROUP BY developer;

-- ✅ Usa la expresión completa o HAVING
SELECT developer, COUNT(*) AS total
FROM videogames
GROUP BY developer
HAVING COUNT(*) > 1;

WHERE se ejecuta en el paso 2, pero el alias total se define en el paso 5 (SELECT). Por eso no puede encontrarlo.

Ojo con SQLite: SQLite es más permisivo que el estándar y permite usar alias del SELECT en WHERE (y en HAVING). Sin embargo, la mayoría de motores (PostgreSQL, MySQL, SQL Server) y el propio estándar SQL no lo permiten. Apóyate siempre en el modelo mental del orden de ejecución: es el que funciona en todos los motores y evita sorpresas al cambiar de base de datos.

2. No puedes usar funciones de agregación en WHERE

-- ❌ Esto da error: no se pueden usar agregaciones en WHERE
SELECT developer, COUNT(*) AS total
FROM videogames
WHERE COUNT(*) > 1
GROUP BY developer;

-- ✅ Usa HAVING para filtrar resultados de agregaciones
SELECT developer, COUNT(*) AS total
FROM videogames
GROUP BY developer
HAVING COUNT(*) > 1;

Las funciones como COUNT(), SUM() o AVG() necesitan que los grupos ya estén formados. Como WHERE se ejecuta antes de GROUP BY, no tiene acceso a ellas.

3. SÍ puedes usar alias del SELECT en ORDER BY

-- ✅ Esto funciona perfectamente
SELECT developer, COUNT(*) AS total
FROM videogames
GROUP BY developer
ORDER BY total DESC;

ORDER BY se ejecuta en el paso 6, después de SELECT (paso 5), por lo que sí puede acceder a los alias definidos ahí.

Ponlo en práctica

Usa la tabla videogames para construir consultas complejas que combinen todas las cláusulas aprendidas:

Nombre de la Tabla: videogames

id title developer year playtime_hours
1 The Legend of Zelda Nintendo 1986 20
2 Super Mario Bros. Nintendo 1985 10
3 Final Fantasy VII Square Enix 1997 40
4 The Witcher 3 CD Projekt Red 2015 100
5 Minecraft Mojang Studios 2011 9999
6 Grand Theft Auto V Rockstar Games 2013 80
7 Dark Souls FromSoftware 2011 60
8 Portal 2 Valve 2011 8
9 Red Dead Redemption 2 Rockstar Games 2018 70
10 The Last of Us Naughty Dog 2013 15
11 Halo: Combat Evolved Bungie 2001 10
12 God of War Santa Monica Studio 2018 25

Tablas de esta lección

videogames5 cols

Estructura

🔑idINTEGERtitleTEXTdeveloperTEXTyearINTEGERplaytime_hoursINTEGER

Datos de ejemplo (5 filas)

idtitledeveloperyearplaytime_hours
1The Legend of ZeldaNintendo198620
2Super Mario Bros.Nintendo198510
3Final Fantasy VIISquare Enix199740
4The Witcher 3CD Projekt Red2015100
5MinecraftMojang Studios20119999
6Grand Theft Auto VRockstar Games201380
7Dark SoulsFromSoftware201160
8Portal 2Valve20118
9Red Dead Redemption 2Rockstar Games201870
10The Last of UsNaughty Dog201315
11Halo: Combat EvolvedBungie200110
12God of WarSanta Monica Studio201825

Ejercicios

Muestra el desarrollador y el número de juegos (alias 'total'), solo para desarrolladores con más de 1 juego, ordenados por total de forma descendente.

sql

Selecciona el desarrollador y su promedio de horas de juego (alias 'promedio'), pero solo para juegos publicados después de 2000, y muestra solo los que tienen un promedio mayor a 30.

sql

Muestra el año y la cantidad de juegos (alias 'total') publicados ese año, solo para años después del 2000, con al menos 2 juegos, ordenados por total descendente.

sql