20 ejercicios de SQL resueltos: SELECT, WHERE, JOIN, GROUP BY y subconsultas


Estos 20 ejercicios permiten practicar SQL de forma progresiva. Antes de mirar cada solución, intentá resolver el enunciado por tu cuenta.

Base de datos utilizada

Trabajamos con clientes, categorías, productos, ventas y ventas_detalles.

Las relaciones principales son:

  • productos.categoria_id → categorias.id;
  • ventas.cliente_id → clientes.id;
  • ventas_detalles.venta_id → ventas.id;
  • ventas_detalles.producto_id → productos.id.

Conviene tener este mapa mental antes de resolver los ejercicios con JOIN.

Cómo leer cada ejercicio

Antes de mirar la solución, intentá responder:

  1. ¿qué resultado final necesito?
  2. ¿qué tabla tiene esa información?
  3. ¿necesito filtrar filas?
  4. ¿necesito relacionar tablas?
  5. ¿necesito agrupar o calcular un resumen?

Resolver SQL es, en gran parte, aprender a traducir una pregunta del negocio a esas decisiones.

1. Mostrar todos los clientes

SELECT * FROM clientes;

Explicación: Usamos SELECT * porque queremos todas las columnas de todas las filas.

2. Mostrar nombre y apellido

SELECT nombre, apellido FROM clientes;

Explicación: Seleccionar solo las columnas necesarias hace la consulta más clara.

3. Clientes de Santa Rosa

SELECT * FROM clientes WHERE ciudad = 'Santa Rosa';

Explicación: WHERE filtra las filas por ciudad. La consulta primero parte de todos los clientes y después conserva solamente los que cumplen la condición.

4. Productos con precio mayor a 100000

SELECT nombre, precio FROM productos WHERE precio > 100000;

Explicación: El operador > compara valores numéricos.

5. Productos con stock bajo

SELECT nombre, stock FROM productos WHERE stock < 10;

Explicación: Este tipo de consulta puede utilizarse para alertas de reposición.

6. Ordenar productos por precio

SELECT nombre, precio FROM productos ORDER BY precio DESC;

Explicación: DESC ordena del valor más alto al más bajo.

7. Tres productos más caros

SELECT nombre, precio FROM productos ORDER BY precio DESC LIMIT 3;

Explicación: Primero ordenamos y luego LIMIT conserva solo las tres primeras filas.

8. Contar productos

SELECT COUNT(*) AS total_productos FROM productos;

Explicación: COUNT(*) devuelve cuántas filas tiene la tabla.

9. Precio promedio

SELECT AVG(precio) AS precio_promedio FROM productos;

Explicación: AVG calcula la media aritmética de la columna.

10. Productos por categoría

SELECT categoria_id, COUNT(*) AS cantidad
FROM productos
GROUP BY categoria_id;

Explicación: GROUP BY crea un grupo por categoría y COUNT cuenta sus productos. El resultado tendrá una fila por cada categoria_id, no una fila por cada producto.

11. Productos con categoría

SELECT p.nombre AS producto, c.nombre AS categoria
FROM productos AS p
INNER JOIN categorias AS c ON p.categoria_id = c.id;

Explicación: JOIN combina cada producto con la categoría relacionada. La condición p.categoria_id = c.id indica exactamente qué filas deben emparejarse.

12. Ventas con nombre del cliente

SELECT v.id, v.fecha, c.nombre, c.apellido, v.total
FROM ventas AS v
INNER JOIN clientes AS c ON v.cliente_id = c.id;

Explicación: Reemplazamos el identificador del cliente por información legible.

13. Total comprado por cliente

SELECT c.id, c.nombre, c.apellido, SUM(v.total) AS total_comprado
FROM clientes AS c
INNER JOIN ventas AS v ON v.cliente_id = c.id
GROUP BY c.id, c.nombre, c.apellido;

Explicación: SUM acumula las ventas dentro de cada grupo de cliente. Primero JOIN conecta ventas con clientes; después GROUP BY reúne las ventas de la misma persona y finalmente SUM calcula el total.

14. Clientes que gastaron más de 100000

SELECT c.nombre, c.apellido, SUM(v.total) AS total_comprado
FROM clientes AS c
INNER JOIN ventas AS v ON v.cliente_id = c.id
GROUP BY c.id, c.nombre, c.apellido
HAVING SUM(v.total) > 100000;

Explicación: HAVING filtra después de calcular la suma por cliente. No usamos WHERE para SUM(v.total) porque ese valor todavía no existe antes de formar los grupos.

15. Clientes sin ventas

SELECT c.id, c.nombre, c.apellido
FROM clientes AS c
LEFT JOIN ventas AS v ON v.cliente_id = c.id
WHERE v.id IS NULL;

Explicación: LEFT JOIN conserva clientes sin coincidencia; NULL identifica los que nunca compraron. Es un patrón muy usado para buscar “registros sin relación”.

16. Productos más vendidos

SELECT p.nombre, SUM(vd.cantidad) AS unidades_vendidas
FROM productos AS p
INNER JOIN ventas_detalles AS vd ON vd.producto_id = p.id
GROUP BY p.id, p.nombre
ORDER BY unidades_vendidas DESC;

Explicación: Sumamos cantidades por producto y ordenamos el ranking.

17. Producto con mayor facturación

SELECT p.nombre, SUM(vd.subtotal) AS facturacion
FROM productos AS p
INNER JOIN ventas_detalles AS vd ON vd.producto_id = p.id
GROUP BY p.id, p.nombre
ORDER BY facturacion DESC
LIMIT 1;

Explicación: El primer registro del ranking es el producto con mayor facturación.

18. Ventas por encima del promedio

SELECT id, cliente_id, total
FROM ventas
WHERE total > (SELECT AVG(total) FROM ventas);

Explicación: La subconsulta calcula el promedio y la consulta externa compara cada venta. Conviene ejecutar primero la subconsulta sola para comprobar qué valor produce.

19. Productos nunca vendidos

SELECT p.id, p.nombre
FROM productos AS p
LEFT JOIN ventas_detalles AS vd ON vd.producto_id = p.id
WHERE vd.id IS NULL;

Explicación: Buscamos productos que no tienen ninguna fila relacionada en detalles.

20. Cliente que más gastó

SELECT c.id, c.nombre, c.apellido, SUM(v.total) AS total_gastado
FROM clientes AS c
INNER JOIN ventas AS v ON v.cliente_id = c.id
GROUP BY c.id, c.nombre, c.apellido
ORDER BY total_gastado DESC
LIMIT 1;

Explicación: Agrupamos, sumamos, ordenamos y conservamos el primer cliente.

Qué conceptos aparecen en estos 20 ejercicios

  • selección de columnas;
  • filtros con WHERE;
  • orden y límites;
  • funciones de agregación;
  • GROUP BY y HAVING;
  • INNER JOIN y LEFT JOIN;
  • subconsultas;
  • rankings simples.

Cómo practicar

  1. identificá qué tabla contiene el dato;
  2. decidí si necesitás WHERE;
  3. si hay varias tablas, buscá la relación;
  4. si necesitás resumir, pensá en GROUP BY;
  5. recién después escribí SQL.

¿Qué sigue?

20 ejercicios intermedios y avanzados.

¿Te sirvió esta guía? ☕

Si este contenido te ayudó y querés apoyar a Club Programador para seguir publicando ejercicios, proyectos y guías gratuitas, podés colaborar mediante:

☕ Apoyar con Mercado Pago

🌎 Apoyar con PayPal


Ruta SQL / MySQL

Ver todos los contenidos de SQL / MySQL

← Proyecto práctico SQL/MySQL

20 ejercicios intermedios y avanzados →


Descubre más desde Club Programador

Suscríbete y recibe las últimas entradas en tu correo electrónico.

2 opiniones en “20 ejercicios de SQL resueltos: SELECT, WHERE, JOIN, GROUP BY y subconsultas”

Deja un comentario

Descubre más desde Club Programador

Suscríbete ahora para seguir leyendo y obtener acceso al archivo completo.

Seguir leyendo