Preguntas de entrevista de SQL, con respuestas que puedes ejecutar
La mayoría de las entrevistas de SQL repiten la misma docena de ideas. A continuación tienes las habituales, con una respuesta breve y una consulta que funciona en PostgreSQL. Los ejemplos usan una pequeña base de datos de una panadería (customers, products, orders y order_items), así que puedes probar cada una en una lección de este sitio.
Encuentra el segundo valor más alto
Una respuesta sencilla es ordenar en orden descendente y saltarte una fila. Devuelve una sola fila, aunque varias filas compartan el segundo precio.
Si los empates importan, ordena con DENSE_RANK y quédate con el puesto 2. DENSE_RANK no deja huecos después de los empates, así que el puesto 2 siempre es el segundo valor distinto.
SELECT name, unit_price FROM ( SELECT name, unit_price, DENSE_RANK() OVER (ORDER BY unit_price DESC) AS r FROM products ) AS ranked WHERE r = 2;
Resultado: Chocolate cake slice, a 4.20.
Encuentra duplicados
Agrupa por la columna que debería ser única y quédate con los grupos que tienen más de una fila.
SELECT order_date, COUNT(*) AS orders FROM orders GROUP BY order_date HAVING COUNT(*) > 1 ORDER BY order_date;
Resultado: Tres fechas, cada una con dos pedidos: 1, 2 y 6 de septiembre.
Encuentra filas sin coincidencia
Usa un LEFT JOIN y conserva las filas en las que el lado derecho es NULL, o usa NOT EXISTS. Ambas sirven para responder «¿qué clientes nunca hicieron un pedido?».
Evita NOT IN con una subconsulta que pueda devolver NULL: un solo NULL hace que toda la condición sea desconocida y no obtienes ninguna fila.
SELECT c.first_name, c.last_name FROM customers AS c LEFT JOIN orders AS o ON o.customer_id = c.customer_id WHERE o.order_id IS NULL ORDER BY c.customer_id;
Resultado: Grace Kim y Hugo Meyer.
Fila superior de cada grupo
Ordena dentro de cada grupo con PARTITION BY y, en una consulta externa, quédate con el puesto 1. Usa RANK para conservar los empates, o ROW_NUMBER para conservar exactamente una fila por grupo.
SELECT category, name, units
FROM (
SELECT p.category, p.name, SUM(oi.quantity) AS units,
RANK() OVER (PARTITION BY p.category ORDER BY SUM(oi.quantity) DESC) AS rk
FROM products AS p
JOIN order_items AS oi ON oi.product_id = p.product_id
GROUP BY p.category, p.name
) AS ranked
WHERE rk = 1
ORDER BY category, name;Resultado: El producto más vendido de cada categoría. Cake muestra dos productos porque empatan con 3 unidades.
Total acumulado
Usa SUM como función de ventana con ORDER BY. Ordena por una columna sin empates, o las filas empatadas se sumarán juntas.
SELECT order_id,
SUM(quantity) AS units,
SUM(SUM(quantity)) OVER (ORDER BY order_id) AS running_units
FROM order_items
GROUP BY order_id
ORDER BY order_id;Resultado: Unidades por pedido y el total acumulado hasta ese punto, que termina en 56.
WHERE frente a HAVING
WHERE filtra las filas antes de agruparlas, así que no puede usar una función de agregación. HAVING filtra los grupos después de la agregación. En el ejemplo, WHERE quita primero los productos baratos, y HAVING conserva las categorías con al menos dos de los que quedan.
SELECT category, COUNT(*) AS products FROM products WHERE unit_price > 2.50 GROUP BY category HAVING COUNT(*) >= 2 ORDER BY category;
Resultado: Bread y cake, con dos productos cada una por encima de 2.50. Pastry y drinks tienen solo un producto por encima de 2.50 y se descartan.
UNION frente a UNION ALL
UNION elimina las filas duplicadas, lo que requiere trabajo extra. UNION ALL conserva todo y es más rápido. Usa UNION ALL salvo que necesites eliminar los duplicados.
SELECT city FROM customers UNION SELECT city FROM customers ORDER BY city;
Resultado: Cinco ciudades, cada una una vez. Con UNION ALL habría 16 filas.
Preguntas frecuentes
- ¿Cuál es la diferencia entre DELETE, TRUNCATE y DROP?
- DELETE elimina las filas que elijas (WHERE) y se puede revertir. TRUNCATE vacía toda la tabla rápidamente y conserva su estructura. DROP elimina la tabla en sí, con su estructura y sus datos.
- ¿Cuál es la diferencia entre INNER JOIN y LEFT JOIN?
- INNER JOIN conserva solo las filas que coinciden en ambos lados. LEFT JOIN conserva todas las filas de la tabla izquierda y rellena el lado derecho con NULL donde no hay coincidencia.
- ¿Cuál es la diferencia entre RANK, DENSE_RANK y ROW_NUMBER?
- Las tres numeran las filas de un orden. RANK da el mismo número a los empates y salta los números siguientes. DENSE_RANK da el mismo número a los empates y no salta ninguno. ROW_NUMBER nunca repite un número.
- ¿Qué dialecto de SQL usan estas respuestas?
- PostgreSQL. LIMIT/OFFSET, las funciones de ventana, los CTEs y los JOIN funcionan casi en todas partes. En SQL Server usa TOP u OFFSET FETCH en lugar de LIMIT, y en Oracle usa FETCH FIRST.