SQL · Guías · 30 de octubre de 2026 · 12 min de lectura
SQL o Excel para análisis de datos: en qué gana cada uno y cómo dar el salto

Excel y SQL no compiten tanto como parece: son herramientas para fases distintas del mismo trabajo. SQL es mejor para obtener, cruzar y resumir datos: trabaja con millones de filas, lee los datos directamente de donde están y una consulta es un registro escrito de exactamente lo que hiciste, que puedes volver a ejecutar mañana. Excel es mejor para mirar, retocar y presentar un resultado pequeño: modelos de escenarios, gráficos rápidos, correcciones a mano y un archivo que cualquiera en la empresa puede abrir. La mayoría de los analistas usan los dos a diario: SQL para sacar una tabla de unos cientos de filas y Excel o una herramienta de BI para trabajar con ella.
Si ya sabes Excel, sabes más SQL de lo que crees. Una tabla dinámica es GROUP BY. BUSCARV es un JOIN. Un filtro es WHERE. Esta guía traduce tus costumbres de Excel a SQL con consultas que se ejecutan sobre la base de datos de una aerolínea del curso de SQL de Nomto (104 aeropuertos, 33.121 vuelos, 262.788 reservas, valores en inglés y dinero en dólares). Todas las tablas de resultados son la salida real.
La respuesta corta: cuándo usar cada uno
| Tarea | Mejor en | Por qué |
|---|---|---|
| Sacar datos de la base de datos de la empresa | SQL | los datos viven ahí; exportar es un paso manual que se queda desfasado |
| Más de un millón de filas, más o menos | SQL | una hoja de Excel admite como máximo 1.048.576 filas |
| Cruzar varias tablas | SQL | un JOIN en lugar de una columna de búsquedas por tabla |
| Un informe que rehaces cada semana | SQL | vuelves a ejecutar la consulta; no hay pasos de copiar y pegar que olvidar |
| Comprobar de dónde sale una cifra | SQL | la consulta es la receta completa |
| Escenarios y modelos financieros | Excel | cambias una celda y ves cómo se actualizan todas las cifras que dependen de ella |
| Un vistazo rápido a un archivo pequeño | Excel | abrir, ordenar, mirar y listo |
| Ediciones a mano, notas, colores | Excel | SQL no te deja escribir dentro de un resultado |
| Gráficos para una reunión en cinco minutos | Excel | vienen de serie y todo el mundo los conoce |
| Compartir con gente que no programa | Excel | todo el mundo lo tiene y lo sabe abrir |
Una regla útil: si el trabajo es «encontrar, combinar y contar», empieza en SQL. Si el trabajo es «jugar con esta tabla y enseñársela a alguien», Excel sirve, y muchas veces es mejor.
Por qué el límite de filas importa más de lo que parece
En la base de datos del curso, ticket_flights (una fila por pasajero y tramo de vuelo) tiene 1.045.726 filas, que caben en una hoja por muy poco. La tabla de eventos de la app directamente no cabe:
SELECT COUNT(*) FROM app_events;
| count_star() |
|---|
| 1494723 |
Y caber no es lo mismo que trabajar con comodidad: un libro con un millón de filas de búsquedas y fórmulas tarda en recalcular. En SQL el tamaño de la tabla apenas cambia cómo escribes la consulta.
Filtros → WHERE
En Excel pulsas la flecha del filtro y marcas valores. En SQL escribes la condición. Reservas hechas desde agosto por 1.000 dólares o más, y cuánto suman:
SELECT COUNT(*) AS bookings, SUM(total_amount) AS revenue
FROM bookings
WHERE book_date >= '2026-08-01'
AND total_amount >= 1000;
| bookings | revenue |
|---|---|
| 16081 | 29341684.00 |
Las equivalencias:
| Filtro de Excel | SQL |
|---|---|
| marcar «Arrived» y «Departed» | WHERE status IN ('Arrived', 'Departed') |
| Filtros de número: mayor o igual que | WHERE total_amount >= 1000 |
| Filtros de texto: comienza por | WHERE city LIKE 'Novo%' |
| Filtros de fecha: entre | WHERE book_date >= '2026-08-01' AND book_date < '2026-09-01' |
| (Vacías) | WHERE actual_departure IS NULL |
Hay una diferencia que pilla a quien viene de Excel: en SQL una celda vacía es NULL, y = NULL nunca coincide con nada. Usa IS NULL.
Ordenar y los 10 mejores → ORDER BY y LIMIT
«Ordenar de mayor a menor y mirar los cinco primeros» se escribe así:
SELECT book_ref, book_date, total_amount
FROM bookings
ORDER BY total_amount DESC
LIMIT 5;
| book_ref | book_date | total_amount |
|---|---|---|
| 3B54BB | 2026-07-01 17:08:00 | 12045.00 |
| 3AC131 | 2026-07-27 01:06:00 | 10871.00 |
| 65A6EA | 2026-06-29 06:28:00 | 10656.00 |
| D7E9AA | 2026-08-04 05:29:00 | 10628.00 |
| EF479E | 2026-07-29 15:58:00 | 10351.00 |
En Excel, ordenar cambia la hoja. En SQL solo cambia este resultado; la tabla se queda como estaba.
BUSCARV / BUSCARX → JOIN
En flights los aeropuertos y los aviones aparecen solo como códigos. En Excel añadirías tres columnas de búsqueda, cada una apuntando a otra hoja. En SQL son tres JOIN en una sola consulta:
SELECT f.flight_no,
f.scheduled_departure,
dep.city AS from_city,
arr.city AS to_city,
a.model
FROM flights f
JOIN airports dep ON dep.airport_code = f.departure_airport
JOIN airports arr ON arr.airport_code = f.arrival_airport
JOIN aircrafts a ON a.aircraft_code = f.aircraft_code
WHERE f.departure_airport = 'SVO'
AND f.scheduled_departure >= '2026-08-01'
AND f.scheduled_departure < '2026-08-02'
ORDER BY f.scheduled_departure, f.flight_no
LIMIT 4;
| flight_no | scheduled_departure | from_city | to_city | model |
|---|---|---|---|---|
| PG0120 | 2026-08-01 09:00:00 | Moscow | Mirny | Boeing 737-300 |
| PG0591 | 2026-08-01 09:00:00 | Moscow | Tomsk | Sukhoi Superjet-100 |
| PG0241 | 2026-08-01 09:40:00 | Moscow | Cheboksary | Sukhoi Superjet-100 |
| PG0677 | 2026-08-01 09:40:00 | Moscow | Makhachkala | Boeing 737-300 |
Fíjate en que la misma tabla airports se une dos veces, una por cada extremo del vuelo, con alias distintos. En Excel serían dos búsquedas separadas contra la misma hoja.
Hay dos comportamientos distintos a BUSCARV, y los dos importan:
Sin coincidencia. BUSCARV muestra #N/D. Un JOIN interno descarta la fila sin avisar. Si quieres conservarla con un valor vacío, usa LEFT JOIN. Aquí está el único modelo de avión sin vuelos, que un JOIN interno escondería:
SELECT a.model
FROM aircrafts a
LEFT JOIN flights f ON f.aircraft_code = a.aircraft_code
WHERE f.flight_id IS NULL;
| model |
|---|
| Airbus A320-200 |
Varias coincidencias. BUSCARV devuelve la primera coincidencia e ignora el resto. Un JOIN devuelve todas, repitiendo la fila una vez por cada una. Una reserva puede tener hasta cinco billetes:
SELECT b.book_ref, b.total_amount, COUNT(t.ticket_no) AS tickets
FROM bookings b
JOIN tickets t ON t.book_ref = b.book_ref
GROUP BY b.book_ref, b.total_amount
ORDER BY tickets DESC, b.book_ref
LIMIT 3;
| book_ref | total_amount | tickets |
|---|---|---|
| 070133 | 1133.00 | 5 |
| 070682 | 8012.00 | 5 |
| 111C34 | 2120.00 | 5 |
Así que si unes las reservas con los billetes y luego sumas total_amount, cada reserva se cuenta una vez por billete:
SELECT (SELECT SUM(total_amount) FROM bookings) AS correct,
SUM(b.total_amount) AS after_join
FROM bookings b
JOIN tickets t ON t.book_ref = b.book_ref;
| correct | after_join |
|---|---|
| 207669809.00 | 343206192.00 |
Es el error de SQL más común entre quienes vienen de Excel, porque BUSCARV nunca multiplica filas. Antes de unir, pregúntate: por cada fila de la izquierda, ¿cuántas filas pueden coincidir a la derecha? La guía de JOIN en SQL lo explica con detalle.
Tabla dinámica → GROUP BY
Área de filas = columnas de GROUP BY. Área de valores = agregados. Ingresos por clase de cabina, con la cuota de cada clase sobre el total (en una tabla dinámica: «Mostrar valores como % del total general»):
SELECT fare_conditions,
COUNT(*) AS segments,
SUM(amount) AS revenue,
ROUND(100.0 * SUM(amount) / SUM(SUM(amount)) OVER (), 1) AS pct_of_revenue
FROM ticket_flights
GROUP BY fare_conditions
ORDER BY revenue DESC;
| fare_conditions | segments | revenue | pct_of_revenue |
|---|---|---|---|
| Economy | 920793 | 146956844.00 | 70.8 |
| Business | 107642 | 55051796.00 | 26.5 |
| Comfort | 17291 | 5661169.00 | 2.7 |
Eso ha recorrido más de un millón de filas. SUM(SUM(amount)) OVER () es una función de ventana que pone el total general junto a cada grupo; las funciones de ventana SQL explican cómo.
Una tabla dinámica con área de columnas (estados en filas, meses en columnas) es un conteo condicional por columna:
SELECT status,
COUNT(*) FILTER (WHERE EXTRACT(MONTH FROM scheduled_departure) = 7) AS jul,
COUNT(*) FILTER (WHERE EXTRACT(MONTH FROM scheduled_departure) = 8) AS aug,
COUNT(*) FILTER (WHERE EXTRACT(MONTH FROM scheduled_departure) = 9) AS sep,
COUNT(*) AS total
FROM flights
GROUP BY status
ORDER BY total DESC;
| status | jul | aug | sep | total |
|---|---|---|---|---|
| Arrived | 10821 | 5886 | 0 | 16707 |
| Scheduled | 0 | 10345 | 5038 | 15383 |
| On Time | 0 | 518 | 0 | 518 |
| Cancelled | 5 | 6 | 403 | 414 |
| Departed | 0 | 58 | 0 | 58 |
| Delayed | 0 | 41 | 0 | 41 |
Aquí Excel es, sinceramente, más cómodo: la tabla dinámica crea las columnas por ti, mientras que en SQL tienes que enumerarlas. Muchos analistas se reparten el trabajo justo así: SQL produce la tabla larga (estado, mes, recuento) y la tabla dinámica de Excel o la herramienta de BI la despliega en columnas.
El área de filtros de la tabla dinámica es WHERE (antes de agrupar), y «mostrar solo los grupos cuyo total supera N» es HAVING. Lo tienes en GROUP BY y HAVING.
Fórmulas → expresiones
| Excel | SQL |
|---|---|
=A2*B2, =REDONDEAR(A2;2) |
price * qty, ROUND(amount, 2) en SELECT |
=SI(A2>=1000;"large";"small") |
CASE WHEN total_amount >= 1000 THEN 'large' ELSE 'small' END |
=SI.ERROR(A2/B2;"") |
a / NULLIF(b, 0) |
=CONTAR.SI(rango;"Cancelled") |
COUNT(*) FILTER (WHERE status = 'Cancelled') |
=SUMAR.SI.CONJUNTO(importe;clase;"Business") |
SUM(amount) FILTER (WHERE fare_conditions = 'Business') |
=A2&" "&B2 |
a || ' ' || b |
=IZQUIERDA(A2;3), =MAYUSC(A2), =ESPACIOS(A2) |
LEFT(s, 3), UPPER(s), TRIM(s) |
=FIN.MES, =AÑO, =A2-B2 con fechas |
DATE_TRUNC, EXTRACT(YEAR FROM d), d1 - d2 |
| Quitar duplicados | SELECT DISTINCT / COUNT(DISTINCT col) |
una columna de total acumulado =C1+B2 |
SUM(x) OVER (ORDER BY day) |
(Los nombres de las funciones son los de Excel en español; en inglés son ROUND, IF, IFERROR, COUNTIF, SUMIFS, LEFT, UPPER, TRIM, EOMONTH y YEAR.)
El gran cambio de mentalidad: una fórmula de Excel vive en una celda y la arrastras hacia abajo. Una expresión de SQL se escribe una vez y se aplica a todas las filas. Los SI anidados se convierten en un CASE, que se lee de arriba abajo:
SELECT book_ref, total_amount,
CASE WHEN total_amount >= 1000 THEN 'large'
WHEN total_amount >= 300 THEN 'medium'
ELSE 'small'
END AS size
FROM bookings
ORDER BY book_ref
LIMIT 4;
| book_ref | total_amount | size |
|---|---|---|
| 00000F | 2657.00 | large |
| 000012 | 379.00 | medium |
| 000068 | 181.00 | small |
| 000181 | 1318.00 | large |
Y la columna que añadirías al lado para luego hacer una tabla dinámica con ella es un GROUP BY más:
SELECT CASE WHEN total_amount >= 1000 THEN 'large'
WHEN total_amount >= 300 THEN 'medium'
ELSE 'small'
END AS size,
COUNT(*) AS bookings
FROM bookings
GROUP BY size
ORDER BY bookings DESC;
| size | bookings |
|---|---|
| medium | 130009 |
| small | 68305 |
| large | 64474 |
Quitar duplicados; por ejemplo, cuántas ciudades distintas tienen aeropuerto:
SELECT COUNT(*) AS airports, COUNT(DISTINCT city) AS cities
FROM airports;
| airports | cities |
|---|---|
| 104 | 101 |
Donde Excel gana de verdad
Conviene ser honestos, porque «SQL es mejor» no vale para todo:
- Modelos. Un presupuesto, una previsión o un escenario de precios en el que cambias una hipótesis y ves moverse lo demás es justo para lo que se inventaron las hojas de cálculo. SQL no tiene celdas que cambiar.
- Datos pequeños, desordenados y de un solo uso. Una lista que alguien te ha mandado por correo, con celdas combinadas y notas al margen, se limpia antes a mano que cargándola en una base de datos.
- Introducir datos a mano. Añadir un comentario, corregir un valor, colorear las filas que quieres comentar.
- Comunicación. Tu responsable puede abrir un libro de Excel. La mayoría no sabe abrir una consulta.
- Power Query y el modelo de datos. El Excel moderno puede cargar y cruzar más datos de los que caben en una hoja. Si tu empresa funciona con Excel, estas funciones cierran parte de la brecha, aunque la lógica sigue siendo más difícil de revisar que una consulta.
Lo que SQL te da a cambio es reproducibilidad. Una hoja de cálculo que ha pasado por veinte pasos manuales no se puede revisar ni rehacer fácilmente; una consulta se puede leer línea a línea, volver a ejecutar con los datos del mes siguiente y que la revise un compañero.
Cómo dar el salto: un camino práctico
- Aprende a leer una fila. Antes de cada consulta, ten claro qué significa una fila de cada tabla (un vuelo, una reserva, un tramo de un billete). Esto sustituye la costumbre de desplazarte por la hoja.
- Empieza por lo que ya haces en Excel. Filtro →
WHERE, ordenar →ORDER BY, tabla dinámica →GROUP BY. Rehaz en SQL uno de tus informes semanales reales. - Luego, los JOIN. Sustituye tus BUSCARV y comprueba el número de filas antes y después de cada JOIN.
- Deja Excel para el último paso. Exporta el resultado final, ya pequeño, a una hoja para los gráficos y los comentarios. No es hacer trampa: así trabaja la mayoría de los analistas.
- Añade
CASE, CTE y funciones de ventana cuando lo básico te salga solo. La chuleta SQL los tiene todos en una página.
En la sala de SQL de Nomto ejecutas estas consultas en el navegador sobre la base de datos de la aerolínea, sin instalar nada, y el curso empieza justo por las operaciones que se parecen a Excel: elegir columnas, filtrar, ordenar y agrupar. Las consultas SQL básicas son una buena primera lectura.
Preguntas frecuentes
¿SQL es más difícil de aprender que Excel?
Lo básico no. Si sabes montar una tabla dinámica y usar BUSCARV, puedes aprender SELECT, WHERE, GROUP BY y JOIN en unas semanas. Lo que requiere práctica es pensar en tablas enteras en lugar de en celdas sueltas, y darte cuenta de cuándo un JOIN multiplica filas.
¿SQL puede sustituir a Excel por completo?
Para obtener y resumir datos, en gran parte sí. Para modelos, ediciones a mano y presentaciones rápidas, no. La mayoría de los analistas usan SQL para producir un resultado pequeño y una hoja de cálculo o una herramienta de BI para trabajar con él.
¿Los analistas de datos siguen usando Excel?
Sí, y mucho, sobre todo en el último paso de un análisis y para compartir resultados. SQL es lo que obtiene los datos; Excel, Google Sheets o una herramienta de BI suele ser lo que ve la gente.
¿Cuál es el equivalente de BUSCARV en SQL?
Un JOIN por la columna de búsqueda: FROM flights f JOIN aircrafts a ON a.aircraft_code = f.aircraft_code. Usa LEFT JOIN si quieres conservar las filas sin coincidencia, igual que BUSCARV conserva la fila y muestra #N/D.
También en English, Português (Brasil), Tiếng Việt, 简体中文