Tema
SELECT básico
SELECT es el comando que más vas a escribir en tu vida como desarrollador: cada listado, buscador, reporte o página de detalle de una app lo usa. En esta lección aprenderás a elegir columnas, renombrarlas, calcular valores, filtrar con WHERE, ordenar con ORDER BY y paginar con LIMIT.
Antes de empezar
Asegúrate de tener cargados el esquema y los datos originales de la tienda. Todos los resultados mostrados salen de ellos.
Concepto
Una consulta SELECT es una pregunta a la base de datos. La respuesta siempre es una tabla (aunque tenga una sola fila o ninguna).
sql
SELECT columnas -- ¿qué quiero ver?
FROM tabla -- ¿de dónde?
WHERE condición -- ¿qué filas?
ORDER BY columna -- ¿en qué orden?
LIMIT n; -- ¿cuántas?Elegir columnas
sql
-- Todas las columnas
SELECT * FROM categorias;| id | nombre |
|---|---|
| 1 | Electrónica |
| 2 | Libros |
| 3 | Hogar |
| 4 | Deportes |
sql
-- Solo algunas columnas, en el orden que quieras
SELECT nombre, precio FROM productos;| nombre | precio |
|---|---|
| Audífonos Bluetooth | 899.00 |
| Teclado mecánico | 1250.00 |
| Monitor 24 pulgadas | 3499.00 |
| Libro Aprende SQL | 349.00 |
| Cien años de soledad | 289.00 |
| Lámpara de escritorio | 459.00 |
| Taza térmica | 199.00 |
| Cable USB-C | 99.00 |
Buena práctica
SELECT * está bien para explorar, pero en tu aplicación pide solo las columnas que necesitas: viaja menos información por la red, se aprovechan mejor los índices y tu código no se rompe si alguien agrega columnas.
Alias y columnas calculadas
Con AS renombras columnas en el resultado. Y puedes hacer cálculos:
sql
SELECT
nombre,
precio,
stock,
precio * stock AS valor_inventario, -- cálculo
precio * 1.16 AS precio_con_iva -- IVA de 16 %
FROM productos;| nombre | precio | stock | valor_inventario | precio_con_iva |
|---|---|---|---|---|
| Audífonos Bluetooth | 899.00 | 25 | 22475.00 | 1042.84 |
| Teclado mecánico | 1250.00 | 10 | 12500.00 | 1450.00 |
| Monitor 24 pulgadas | 3499.00 | 5 | 17495.00 | 4058.84 |
| Libro Aprende SQL | 349.00 | 40 | 13960.00 | 404.84 |
| Cien años de soledad | 289.00 | 30 | 8670.00 | 335.24 |
| Lámpara de escritorio | 459.00 | 15 | 6885.00 | 532.44 |
| Taza térmica | 199.00 | 50 | 9950.00 | 230.84 |
| Cable USB-C | 99.00 | 100 | 9900.00 | 114.84 |
Si el alias lleva espacios, ponlo entre comillas dobles: AS "Precio con IVA". Para redondear: ROUND(precio * 1.16, 2).
Concatenar textos:
sql
-- PostgreSQL y SQLite usan ||; MySQL usa CONCAT() (que también existe en PostgreSQL)
SELECT CONCAT(nombre, ' (', ciudad, ')') AS cliente FROM clientes;| cliente |
|---|
| Ana López (Ciudad de México) |
| Carlos Ruiz (Guadalajara) |
| María Pérez (Monterrey) |
| Jorge Díaz (Ciudad de México) |
| Lucía Gómez (Puebla) |
DISTINCT: valores sin repetir
sql
SELECT DISTINCT ciudad FROM clientes;| ciudad |
|---|
| Ciudad de México |
| Guadalajara |
| Monterrey |
| Puebla |
WHERE: filtrar filas
sql
SELECT nombre, precio
FROM productos
WHERE precio > 1000;| nombre | precio |
|---|---|
| Teclado mecánico | 1250.00 |
| Monitor 24 pulgadas | 3499.00 |
Operadores de comparación
| Operador | Significado | Ejemplo |
|---|---|---|
= | Igual | ciudad = 'Puebla' |
<> o != | Distinto | estado <> 'cancelado' |
> / >= | Mayor / mayor o igual | stock >= 30 |
< / <= | Menor / menor o igual | precio <= 300 |
Combinar condiciones: AND, OR, NOT
sql
-- Electrónica con precio menor a 1000
SELECT nombre, precio
FROM productos
WHERE categoria_id = 1 AND precio < 1000;| nombre | precio |
|---|---|
| Audífonos Bluetooth | 899.00 |
sql
-- Clientes de Monterrey o de Puebla
SELECT nombre, ciudad
FROM clientes
WHERE ciudad = 'Monterrey' OR ciudad = 'Puebla';| nombre | ciudad |
|---|---|
| María Pérez | Monterrey |
| Lucía Gómez | Puebla |
sql
-- Pedidos que NO están cancelados
SELECT id, estado FROM pedidos WHERE NOT estado = 'cancelado';| id | estado |
|---|---|
| 1 | entregado |
| 2 | entregado |
| 3 | enviado |
| 4 | pendiente |
Filtrar por fechas funciona igual (escribe la fecha en formato ISO):
sql
SELECT nombre, fecha_registro
FROM clientes
WHERE fecha_registro >= '2024-03-01';| nombre | fecha_registro |
|---|---|
| Jorge Díaz | 2024-03-11 |
| Lucía Gómez | 2024-04-02 |
Error común
Las comillas: en SQL estándar los textos van entre comillas simples ('Puebla'). Las comillas dobles son para nombres de columnas o tablas. En PostgreSQL, WHERE ciudad = "Puebla" da error: busca una columna llamada Puebla.
ORDER BY: ordenar
sql
-- Del más barato al más caro (ASC es el valor por defecto)
SELECT nombre, precio FROM productos ORDER BY precio;
-- Del más caro al más barato
SELECT nombre, precio FROM productos ORDER BY precio DESC;| nombre | precio |
|---|---|
| Monitor 24 pulgadas | 3499.00 |
| Teclado mecánico | 1250.00 |
| Audífonos Bluetooth | 899.00 |
| Lámpara de escritorio | 459.00 |
| Libro Aprende SQL | 349.00 |
| Cien años de soledad | 289.00 |
| Taza térmica | 199.00 |
| Cable USB-C | 99.00 |
Ordenar por varias columnas (desempata con la segunda):
sql
SELECT nombre, ciudad, fecha_registro
FROM clientes
ORDER BY ciudad ASC, fecha_registro DESC;| nombre | ciudad | fecha_registro |
|---|---|---|
| Jorge Díaz | Ciudad de México | 2024-03-11 |
| Ana López | Ciudad de México | 2024-01-15 |
| Carlos Ruiz | Guadalajara | 2024-02-03 |
| María Pérez | Monterrey | 2024-02-20 |
| Lucía Gómez | Puebla | 2024-04-02 |
Puedes ordenar por un alias o una expresión: ORDER BY valor_inventario DESC.
Los NULL al ordenar
En MySQL y SQLite los NULL salen primero en orden ascendente; en PostgreSQL salen al final. PostgreSQL permite controlarlo con ORDER BY categoria_id NULLS LAST.
LIMIT y OFFSET: cuántas filas
sql
-- Los 3 productos más caros
SELECT nombre, precio
FROM productos
ORDER BY precio DESC
LIMIT 3;| nombre | precio |
|---|---|
| Monitor 24 pulgadas | 3499.00 |
| Teclado mecánico | 1250.00 |
| Audífonos Bluetooth | 899.00 |
LIMIT funciona en MySQL, PostgreSQL y SQLite. En SQL Server se usa SELECT TOP 3 ... y el estándar es FETCH FIRST 3 ROWS ONLY (PostgreSQL también lo acepta).
Paginación
Para mostrar productos de 3 en 3 (página 1, 2, 3...):
sql
-- Página 1
SELECT id, nombre FROM productos ORDER BY id LIMIT 3 OFFSET 0;
-- Página 2
SELECT id, nombre FROM productos ORDER BY id LIMIT 3 OFFSET 3;
-- Página 3
SELECT id, nombre FROM productos ORDER BY id LIMIT 3 OFFSET 6;Resultado de la página 2:
| id | nombre |
|---|---|
| 4 | Libro Aprende SQL |
| 5 | Cien años de soledad |
| 6 | Lámpara de escritorio |
Fórmula: OFFSET = (pagina - 1) * tamaño_pagina.
Error común
Usar LIMIT sin ORDER BY. Sin orden explícito, la BD puede devolver las filas en cualquier orden y tu paginación mostrará productos repetidos o saltará otros.
Paginación profesional
Con millones de filas, OFFSET 500000 es lento porque la BD recorre y descarta 500 mil filas. La alternativa es la paginación por cursor (keyset): WHERE id > :ultimo_id_visto ORDER BY id LIMIT 20. Es lo que usan los "scroll infinitos".
Paso a paso: cómo construir una consulta
Pregunta del cliente: "Quiero ver los 2 productos con más stock que cuesten menos de 500 pesos".
- ¿De qué tabla? →
FROM productos - ¿Qué filas? →
WHERE precio < 500 - ¿Qué columnas? →
SELECT nombre, precio, stock - ¿Qué orden? →
ORDER BY stock DESC - ¿Cuántas? →
LIMIT 2
sql
SELECT nombre, precio, stock
FROM productos
WHERE precio < 500
ORDER BY stock DESC
LIMIT 2;| nombre | precio | stock |
|---|---|---|
| Cable USB-C | 99.00 | 100 |
| Taza térmica | 199.00 | 50 |
Ejercicios
- Muestra nombre y email de todos los clientes ordenados alfabéticamente por nombre.
- Lista los productos con stock menor o igual a 15, del menor al mayor stock.
- Muestra los pedidos de junio de 2024 (fecha entre el 1 y el 30 de junio) con su id, fecha y estado.
- Muestra el producto más barato de la categoría Electrónica (id 1).
- Muestra nombre, precio y el precio con 20 % de descuento (alias
precio_oferta, redondeado a 2 decimales) de los libros (categoría 2).
Ver solución
sql
-- 1
SELECT nombre, email FROM clientes ORDER BY nombre;| nombre | |
|---|---|
| Ana López | ana@correo.com |
| Carlos Ruiz | carlos@correo.com |
| Jorge Díaz | jorge@correo.com |
| Lucía Gómez | lucia@correo.com |
| María Pérez | maria@correo.com |
sql
-- 2
SELECT nombre, stock FROM productos WHERE stock <= 15 ORDER BY stock;| nombre | stock |
|---|---|
| Monitor 24 pulgadas | 5 |
| Teclado mecánico | 10 |
| Lámpara de escritorio | 15 |
sql
-- 3
SELECT id, fecha, estado
FROM pedidos
WHERE fecha >= '2024-06-01' AND fecha <= '2024-06-30';| id | fecha | estado |
|---|---|---|
| 3 | 2024-06-01 | enviado |
| 4 | 2024-06-15 | pendiente |
| 5 | 2024-06-20 | cancelado |
sql
-- 4
SELECT nombre, precio FROM productos
WHERE categoria_id = 1
ORDER BY precio
LIMIT 1;| nombre | precio |
|---|---|
| Audífonos Bluetooth | 899.00 |
sql
-- 5
SELECT nombre, precio, ROUND(precio * 0.80, 2) AS precio_oferta
FROM productos
WHERE categoria_id = 2;| nombre | precio | precio_oferta |
|---|---|---|
| Libro Aprende SQL | 349.00 | 279.20 |
| Cien años de soledad | 289.00 | 231.20 |
Resumen
SELECT columnas FROM tablaconsulta datos; evitaSELECT *en tu código.AScrea alias; puedes calcular columnas (precio * stock).DISTINCTelimina duplicados.WHEREfiltra con=,<>,>,<,AND,OR,NOT. Textos entre comillas simples.ORDER BY ... ASC/DESCordena;LIMITyOFFSETlimitan y paginan (siempre conORDER BY).