Lección 8 de 16 · Nivel 2: Intermedio

Introducción a SQL: SELECT, WHERE y ORDER BY

  • ⏱ 13 min de lectura
  • ❓ 4 preguntas de repaso
  • ✍️ Ejercicio con solución
  • 📥 Plantilla descargable
En esta lección
  1. Qué es una base de datos relacional
  2. Prepara tu base de datos de práctica
  3. Anatomía de una consulta
  4. SELECT y FROM: elige columnas
  5. WHERE: filtra las filas
  6. La trampa de AND y OR
  7. En qué orden «piensa» la base de datos
  8. Errores comunes (y qué hacer en su lugar)
  9. Resumen
Lo que lograrás en esta lección
  • Entender qué es SQL, qué es una base de datos relacional y por qué todo analista lo necesita.
  • Crear una base de datos de práctica con las ventas de Nexo y abrirla en una herramienta gratuita.
  • Escribir consultas con SELECT, FROM, DISTINCT y alias.
  • Filtrar filas con WHERE: comparaciones, BETWEEN, IN, LIKE e IS NULL.
  • Ordenar y limitar resultados con ORDER BY y LIMIT, y evitar la trampa de AND y OR.
📥 Practica esta lección

Con estos dos archivos crearás la base de datos nexo.db (instrucciones abajo).

SQL (Structured Query Language) es el lenguaje para pedirle datos a una base de datos. En lugar de abrir un archivo y filtrar con el mouse, escribes una instrucción como «dame los pedidos de Lima por la web, del más caro al más barato» y la base de datos te devuelve el resultado, aunque la tabla tenga millones de filas. Casi todas las empresas guardan sus ventas, clientes e inventarios en bases de datos, por eso SQL aparece en la gran mayoría de ofertas de analista. La buena noticia: con media docena de palabras clave ya puedes hacer consultas útiles.

3 tablastendrá tu base de práctica: ventas (197 filas), regiones (9) y ventas_sin_limpiar (200)
6 palabrasbastan para esta lección: SELECT, FROM, WHERE, ORDER BY, LIMIT y DISTINCT
GratisSQLite y DB Browser for SQLite no cuestan nada y funcionan sin internet

Qué es una base de datos relacional

Una base de datos relacional guarda la información en tablas (como hojas de Excel con reglas estrictas): cada columna tiene un tipo de dato fijo y cada fila es un registro. Las tablas se relacionan entre sí por columnas comunes; por ejemplo, la tabla ventas y la tabla regiones comparten la columna region. Los sistemas más conocidos son PostgreSQL, MySQL, SQL Server, Oracle, SQLite y, en la nube, BigQuery o Snowflake. Cada uno tiene pequeñas diferencias, pero lo que aprenderás aquí funciona en todos.

Prepara tu base de datos de práctica

La forma más sencilla y fiable de crearla es con Python, aunque todavía no sepas programar: copia este código en Google Colab (gratis, en el navegador) o en tu computadora, con los dos archivos del curso en la misma carpeta, y ejecútalo:

import sqlite3
import pandas as pd

archivo = "ventas-practica-analisis.xlsx"
con = sqlite3.connect("nexo.db")

ventas = pd.read_excel(archivo, sheet_name="Ventas_limpias")
ventas["fecha"] = ventas["fecha"].dt.strftime("%Y-%m-%d")
ventas.to_sql("ventas", con, index=False, if_exists="replace")

pd.read_excel(archivo, sheet_name="Regiones").to_sql(
    "regiones", con, index=False, if_exists="replace")
pd.read_csv("ventas-practica-analisis.csv").to_sql(
    "ventas_sin_limpiar", con, index=False, if_exists="replace")

print(pd.read_sql("SELECT COUNT(*) AS filas FROM ventas", con))   # 197
con.close()

Se crea el archivo nexo.db. Ábrelo con DB Browser for SQLite (programa gratuito), ve a la pestaña «Ejecutar SQL» y ya puedes escribir consultas. Las fechas se guardan como texto en formato AAAA-MM-DD, que se ordena y compara correctamente. Si quieres entender el código, el curso de Python lo explica en la lección de bases de datos con SQLite y SQL.

Anatomía de una consulta

Una consulta básica se escribe siempre en este orden. Solo SELECT y FROM son obligatorias:

  1. SELECT: qué columnas
  2. FROM: de qué tabla
  3. WHERE: qué filas
  4. ORDER BY: en qué orden
  5. LIMIT: cuántas filas

SELECT y FROM: elige columnas

La consulta más simple muestra todas las columnas (*) de una tabla. Con LIMIT ves solo las primeras filas, ideal para conocer una tabla nueva sin cargarla entera:

SELECT *
FROM ventas
LIMIT 5;
id_pedidofecharegionproductocategoriacanalunidadesprecio_unitarioimporte
P-00012025-01-03AntioquiaSilla ergonómicaOficinaWeb1189.0189.0
P-00022025-01-03LimaMouse inalámbricoAccesoriosWeb717.5122.5
P-00032025-01-04LimaTeclado mecánicoAccesoriosMarketplace654.9329.4
P-00042025-01-04BogotáMochila para laptopAccesoriosMarketplace139.939.9
P-00052025-01-09Ciudad de MéxicoAudífonos BluetoothAudioTienda física144.944.9

Para ver valores sin repetir, usa DISTINCT. Esta consulta devuelve las 4 categorías, en orden alfabético: Accesorios, Audio, Cómputo y Oficina.

SELECT DISTINCT categoria
FROM ventas
ORDER BY categoria;

También puedes crear columnas calculadas y ponerles nombre con AS (alias). Esta consulta recalcula el importe de los pedidos con 8 unidades o más:

SELECT id_pedido, producto, unidades, precio_unitario,
       unidades * precio_unitario AS importe_calculado
FROM ventas
WHERE unidades >= 8
ORDER BY unidades DESC, id_pedido;
id_pedidoproductounidadesprecio_unitarioimporte_calculado
P-0133Mouse inalámbrico1217.5210.0
P-0120Mouse inalámbrico1017.5175.0
P-0088Mouse inalámbrico917.5157.5
P-0076Mouse inalámbrico817.5140.0
P-0102Mouse inalámbrico817.5140.0
P-0170Mouse inalámbrico817.5140.0

Curioso: todos los pedidos de 8 unidades o más son de mouse. Los compradores de volumen buscan productos baratos, una pista que retomarás al estudiar correlaciones.

WHERE: filtra las filas

WHERE deja pasar solo las filas que cumplen la condición. Estos son los operadores que más usarás:

OperadorEjemploSignifica
=, <>canal = 'Web'Igual, distinto
>, >=, <, <=importe >= 600Comparaciones numéricas o de fechas
BETWEEN … AND …fecha BETWEEN '2025-12-24' AND '2025-12-31'Entre dos valores, ambos incluidos
IN (…)region IN ('Lima', 'Arequipa')Cualquiera de la lista
LIKEproducto LIKE 'Laptop%'Patrón de texto: % = cualquier cosa
IS NULL, IS NOT NULLimporte IS NULLValor vacío o no vacío
AND, OR, NOTregion = 'Lima' AND canal = 'Web'Combinar condiciones

Los textos y las fechas van entre comillas simples. Una consulta típica combina WHERE, ORDER BY y LIMIT para responder una pregunta tipo «top 5»: ¿cuáles fueron los cinco pedidos web más grandes de Lima?

SELECT id_pedido, fecha, producto, importe
FROM ventas
WHERE region = 'Lima' AND canal = 'Web'
ORDER BY importe DESC
LIMIT 5;
id_pedidofechaproductoimporte
P-00982025-08-06Laptop 14 pulgadas1298.0
P-01152025-09-02Tablet 10 pulgadas837.0
P-01452025-11-07Monitor 24 pulgadas319.8
P-01532025-11-13Parlante portátil239.6
P-01312025-10-05Teclado mecánico219.6
P-00981.298,00
P-0115837,00
P-0145319,80
P-0153239,60
P-0131219,60

El resultado de la consulta como gráfico: cada barra, proporcional al pedido más grande (1.298 USD). Dos pedidos concentran la mayor parte del valor del top 5.

Dato curioso: P-0153 y P-0131 venían escritos como «lima» y «Lima » en la tabla sin limpiar. En ventas_sin_limpiar, esta misma consulta no los encontraría, porque en SQLite (y en PostgreSQL) el = distingue mayúsculas y espacios.

BETWEEN, IN y LIKE en acción

¿Qué laptops se vendieron en las regiones de Perú? Usamos LIKE para el producto e IN para la lista de regiones:

SELECT id_pedido, fecha, region, unidades, importe
FROM ventas
WHERE producto LIKE 'Laptop%'
  AND region IN ('Lima', 'Arequipa', 'La Libertad')
ORDER BY fecha;
id_pedidofecharegionunidadesimporte
P-00922025-07-25Arequipa1649.0
P-00982025-08-06Lima21298.0
P-01362025-10-11Arequipa1649.0
P-01622025-11-25Arequipa21298.0
P-01682025-12-02Lima1649.0

Arequipa compró más laptops que Lima, y todas en el segundo semestre. Para fechas, BETWEEN incluye los dos extremos: WHERE fecha BETWEEN '2025-12-24' AND '2025-12-31' devuelve los 5 pedidos de la última semana del año (P-0193 a P-0197).

1. ¿Qué consulta devuelve los pedidos de Bogotá o Antioquia con importe mayor a 300?

  • SELECT * FROM ventas WHERE region = 'Bogotá' OR 'Antioquia' AND importe > 300;
  • SELECT * FROM ventas WHERE region IN ('Bogotá', 'Antioquia') AND importe > 300;
  • SELECT * FROM ventas WHERE region = 'Bogotá, Antioquia' AND importe > 300;

IN compara contra una lista. La primera opción está mal escrita (cada comparación necesita su columna: region = 'Antioquia') y la tercera busca una región llamada literalmente «Bogotá, Antioquia», que no existe.

Buscar vacíos: IS NULL

En SQL, un valor vacío es NULL y no se compara con =. En la tabla sin limpiar:

SELECT id_pedido, region, producto, unidades, precio_unitario, importe
FROM ventas_sin_limpiar
WHERE importe IS NULL;
id_pedidoregionproductounidadesprecio_unitarioimporte
P-0017BogotáMonitor 24 pulgadas1159.9NULL
P-0035AntioquiaMochila para laptop139.9NULL
P-0068LimaAudífonos Bluetooth144.9NULL
P-0099Ciudad de MéxicoLámpara LED de escritorio327.5NULL

Son los 4 importes vacíos que corregiste en la lección 5. Si escribes WHERE importe = NULL, la consulta devuelve 0 filas sin dar error: NULL significa «desconocido», y nada es igual a algo desconocido.

La trampa de AND y OR

AND se evalúa antes que OR, igual que la multiplicación antes que la suma. Mira la diferencia entre estas dos consultas que parecen iguales:

-- Sin paréntesis: devuelve 101 filas
SELECT COUNT(*) FROM ventas
WHERE canal = 'Web' OR canal = 'Marketplace' AND importe > 500;

-- Con paréntesis: devuelve 14 filas
SELECT COUNT(*) FROM ventas
WHERE (canal = 'Web' OR canal = 'Marketplace') AND importe > 500;

La primera se lee como «todos los pedidos web (94), más los de Marketplace mayores a 500 (7)». La segunda es lo que probablemente querías: pedidos de cualquiera de los dos canales que superan 500. COUNT(*) cuenta filas; lo verás a fondo en la próxima lección. Regla práctica: siempre que mezcles AND y OR, usa paréntesis.

2. ¿Por qué la consulta sin paréntesis devuelve 101 filas?

  • Porque SQL evalúa las condiciones de izquierda a derecha.
  • Porque AND se evalúa primero: devuelve todos los pedidos web más los de Marketplace mayores a 500.
  • Porque COUNT(*) cuenta también las filas vacías.

Sin paréntesis, la condición equivale a canal = 'Web' OR (canal = 'Marketplace' AND importe > 500): 94 pedidos web + 7 de Marketplace = 101.

En qué orden «piensa» la base de datos

Escribes SELECT primero, pero la base de datos lo procesa en otro orden: FROM → WHERE → SELECT → ORDER BY → LIMIT. Primero toma la tabla, luego filtra filas, después elige y calcula columnas, ordena y, al final, corta. Por eso puedes ordenar por un alias creado en SELECT (ORDER BY importe_calculado), pero en muchos sistemas no puedes usar ese alias dentro de WHERE.

Errores comunes (y qué hacer en su lugar)

Escribir textos con comillas dobles: WHERE canal = "Web".

Usa comillas simples para valores: 'Web'. Las dobles, en el estándar, son para nombres de columnas.

Buscar vacíos con = NULL.

Usa IS NULL o IS NOT NULL.

Lanzar SELECT * sin LIMIT sobre una tabla de millones de filas.

Explora con LIMIT y pide solo las columnas que necesitas.

Asumir que 'lima' encontrará «Lima».

Según el sistema, = distingue mayúsculas. Limpia los datos o usa LOWER(region) = 'lima'.

3. ¿Qué devuelve SELECT COUNT(*) AS pedidos_grandes FROM ventas WHERE importe >= 600;?

  • Una sola fila con el número 15
  • Los importes de todos los pedidos ordenados
  • Quince filas, una por pedido

COUNT(*) resume todas las filas que pasan el filtro en un solo número. Hay 15 pedidos de 600 USD o más: los mismos que FILTRAR devolvía en Excel en la lección 4.

4. ¿Cuál es el orden correcto de las cláusulas al escribir la consulta?

  • FROM, SELECT, WHERE, LIMIT, ORDER BY
  • SELECT, WHERE, FROM, ORDER BY, LIMIT
  • SELECT, FROM, WHERE, ORDER BY, LIMIT

Se escribe SELECT, FROM, WHERE, ORDER BY y LIMIT. La base de datos la procesa en otro orden (FROM, WHERE, SELECT, ORDER BY, LIMIT), pero si cambias el orden de escritura obtendrás un error de sintaxis.

Ejercicio práctico

Escribe y ejecuta dos consultas en tu base nexo.db:

  1. Los pedidos de Bogotá por Marketplace con importe mayor a 100, del más caro al más barato (muestra id_pedido, fecha, producto e importe).
  2. Los pedidos de la categoría Oficina de 300 USD o más, con su región y canal, ordenados de mayor a menor importe.
Ver solución
-- 1
SELECT id_pedido, fecha, producto, importe
FROM ventas
WHERE region = 'Bogotá' AND canal = 'Marketplace' AND importe > 100
ORDER BY importe DESC;
id_pedidofechaproductoimporte
P-01542025-11-13Teclado mecánico164.7
P-01732025-12-05Monitor 24 pulgadas159.9
P-00092025-01-21Audífonos Bluetooth134.7
-- 2
SELECT id_pedido, fecha, region, canal, importe
FROM ventas
WHERE categoria = 'Oficina' AND importe >= 300
ORDER BY importe DESC;
id_pedidofecharegioncanalimporte
P-00302025-03-07La LibertadWeb756.0
P-01662025-12-01JaliscoWeb567.0
P-00132025-01-29LimaTienda física378.0
P-00752025-06-16Ciudad de MéxicoMarketplace378.0

En la segunda, todos son pedidos de sillas ergonómicas (189 USD cada una): 4, 3, 2 y 2 unidades. Si el empate entre P-0013 y P-0075 te sale en otro orden, es normal: agrega , id_pedido al ORDER BY para fijarlo.

Resumen

  • SQL consulta bases de datos relacionales: tablas con tipos fijos que se relacionan por columnas comunes.
  • SELECT elige columnas (con alias y cálculos), FROM la tabla y DISTINCT quita repetidos.
  • WHERE filtra con comparaciones, BETWEEN, IN, LIKE e IS NULL; los textos van entre comillas simples.
  • ORDER BY ordena y LIMIT corta: juntos responden preguntas de tipo «top N».
  • Al mezclar AND y OR, usa paréntesis: 101 filas frente a 14 pueden ser la misma consulta mal escrita.

En la próxima lección: SQL intermedio: GROUP BY, HAVING y JOIN. Resumirás ventas por región y canal, filtrarás grupos y unirás la tabla de ventas con la de regiones para analizar por país.

🎓 Guarda tu avance y obtén tu certificado gratis

Crea tu cuenta en 30 segundos, marca tus lecciones y descarga el certificado al terminar.

Inscribirme gratis