SELECT * FROM users Seleccionar todas las columnas de la tabla
SELECT name, email FROM users Seleccionar columnas específicas
SELECT DISTINCT status FROM orders Seleccionar solo valores únicos
SELECT * FROM users WHERE age > 18 Filtrar filas con WHERE
SELECT * FROM users WHERE name LIKE '%john%' Búsqueda de patrones con LIKE
SELECT * FROM users WHERE age BETWEEN 18 AND 30 Filtro de rango con BETWEEN
SELECT * FROM users WHERE status IN ('active', 'pending') Filtrar por conjunto de valores
SELECT * FROM users WHERE email IS NOT NULL Filtrar valores null/no null
SELECT * FROM users ORDER BY name ASC Ordenar resultados ascendentemente
SELECT * FROM users ORDER BY created_at DESC LIMIT 10 Obtener las N primeras filas
SELECT * FROM users LIMIT 10 OFFSET 20 Paginación con offset
SELECT name AS full_name FROM users Alias de columna
INSERT INTO users (name, email)
VALUES ('John', 'john@mail.com') Insertar una fila
INSERT INTO users (name, email)
VALUES
('A', 'a@m.com'),
('B', 'b@m.com') Insertar múltiples filas
UPDATE users SET name = 'Jane'
WHERE id = 1 Actualizar filas que cumplan la condición
DELETE FROM users WHERE id = 1 Eliminar filas que cumplan la condición
TRUNCATE TABLE users Eliminar todas las filas (rápido, sin rollback)
INSERT INTO target SELECT * FROM source
WHERE condition Insertar desde otra consulta
INSERT INTO users (name, email)
VALUES ('John', 'j@m.com')
ON CONFLICT (email) DO UPDATE
SET name = EXCLUDED.name Upsert (insertar o actualizar)
SELECT * FROM users
INNER JOIN orders ON users.id = orders.user_id Inner join (solo filas coincidentes)
SELECT * FROM users
LEFT JOIN orders ON users.id = orders.user_id Left join (todos de la tabla izquierda)
SELECT * FROM users
RIGHT JOIN orders ON users.id = orders.user_id Right join (todos de la tabla derecha)
SELECT * FROM users
FULL OUTER JOIN orders ON users.id = orders.user_id Full outer join (todos de ambas)
SELECT * FROM users
CROSS JOIN products Cross join (producto cartesiano)
SELECT a.name, b.name
FROM employees a
JOIN employees b ON a.manager_id = b.id Self join (auto unión)
SELECT COUNT(*) FROM users Contar todas las filas
SELECT COUNT(DISTINCT status) FROM orders Contar valores distintos
SELECT SUM(amount) FROM orders Suma de valores de la columna
SELECT AVG(age) FROM users Promedio de valores de la columna
SELECT MIN(price), MAX(price) FROM products Valores mínimo y máximo
SELECT status, COUNT(*)
FROM orders
GROUP BY status Agrupar y contar
SELECT status, COUNT(*)
FROM orders
GROUP BY status
HAVING COUNT(*) > 5 Filtrar grupos con HAVING
SELECT department,
STRING_AGG(name, ', ') AS members
FROM employees
GROUP BY department Concatenar valores agrupados
SELECT * FROM users
WHERE id IN (
SELECT user_id FROM orders
) Subconsulta con IN
SELECT * FROM users
WHERE EXISTS (
SELECT 1 FROM orders
WHERE orders.user_id = users.id
) Subconsulta con EXISTS
SELECT *, (
SELECT COUNT(*)
FROM orders
WHERE orders.user_id = users.id
) AS order_count
FROM users Subconsulta correlacionada en SELECT
WITH active_users AS (
SELECT * FROM users
WHERE status = 'active'
)
SELECT * FROM active_users Expresión de tabla común (CTE)
SELECT * FROM (
SELECT *, ROW_NUMBER()
OVER (ORDER BY score DESC) AS rank
FROM students
) ranked
WHERE rank <= 10 Subconsulta con función ventana
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE,
created_at TIMESTAMP DEFAULT NOW()
) Crear tabla con restricciones
ALTER TABLE users ADD COLUMN age INT Añadir columna a la tabla
ALTER TABLE users DROP COLUMN age Eliminar columna de la tabla
ALTER TABLE users
ALTER COLUMN name SET NOT NULL Modificar restricción de columna
DROP TABLE IF EXISTS users Eliminar tabla si existe
ALTER TABLE users
RENAME COLUMN name TO full_name Renombrar columna
ALTER TABLE orders
ADD FOREIGN KEY (user_id)
REFERENCES users(id)
ON DELETE CASCADE Añadir restricción de clave foránea
COALESCE(val1, val2, 'default') Devolver primer valor no nulo
CASE
WHEN age < 18 THEN 'minor'
WHEN age < 65 THEN 'adult'
ELSE 'senior'
END Expresión condicional
CAST(price AS INTEGER) Conversión de tipo
CONCAT(first_name, ' ', last_name) Concatenar cadenas
UPPER(name) / LOWER(name) Convertir mayúsculas/minúsculas
LENGTH(name) / TRIM(name) Longitud de cadena / eliminar espacios
NOW() / CURRENT_DATE / CURRENT_TIMESTAMP Fecha/hora actual
EXTRACT(YEAR FROM created_at) Extraer parte de la fecha
DATE_TRUNC('month', created_at) Truncar fecha a precisión
CREATE INDEX idx_users_email
ON users(email) Crear índice en columna
CREATE UNIQUE INDEX idx_users_email
ON users(email) Crear índice único
CREATE INDEX idx_name_email
ON users(name, email) Índice compuesto (multi-columna)
DROP INDEX idx_users_email Eliminar un índice
EXPLAIN ANALYZE
SELECT * FROM users WHERE email = 'x' Analizar plan de ejecución de consulta
Cheat Sheet de SQL — SELECT, JOIN, GROUP BY y Funciones de Ventana
SQL se estandarizó en 1986 y el dialecto central —SELECT, JOIN, GROUP BY, INSERT, UPDATE, DELETE— apenas ha cambiado en cuarenta años; CTE y funciones de ventana se montan sobre la misma forma. La chuleta de abajo cubre más de 60 consultas entre selects, modificaciones, joins, agregados, subconsultas, DDL, funciones e índices. La mayoría de los líos en consultas reales no vienen de olvidar la sintaxis. Vienen de rarezas que parecen normales pero muerden. `NULL` no es igual a nada, ni a sí mismo, así que `WHERE columna = NULL` no devuelve filas y la forma correcta es `IS NULL`. Un `LEFT JOIN` seguido de un `WHERE` por la tabla derecha se transforma sin avisar en un `INNER JOIN`, porque cualquier fila con `NULL` a la derecha falla el filtro. `COUNT(*)` y `COUNT(columna)` devuelven cifras distintas en consultas idénticas. Estos son los fragmentos que se acaban consultando al depurar eso: el join que conserva el lado izquierdo, el `HAVING` que filtra grupos y no filas, la CTE que aplana una subconsulta anidada, sin releer la referencia de SQL desde la línea uno cada vez.
Trampas habituales en SQL
Hay un puñado de patrones que merecen estar en la primera pantalla de cualquier archivo SQL. `WHERE` filtra filas antes del agrupamiento; `HAVING` filtra grupos después de agregar: poner `COUNT(*) > 5` en `WHERE` lanza error. Hacer join entre tablas cambia el número de filas: un join uno-a-muchos multiplica, y un `SUM` puede contar el doble si la misma fila padre encaja con varios hijos. Los índices rinden en columnas que aparezcan en `WHERE`, `JOIN ON` u `ORDER BY` cuando la selectividad compense el coste de escritura en cada insert; `EXPLAIN ANALYZE` confirma que un índice se está usando. `LIKE 'patrón%'` puede aprovechar un índice btree cuando el comodín va al final, pero `LIKE '%patrón'` no, así que los comodines al principio fuerzan un escaneo de toda la tabla. Las transacciones y los niveles de aislamiento importan: el `READ COMMITTED` por defecto deja que dos lecturas dentro de la misma transacción vean valores distintos, bien para informes pero mal para saldos. La chuleta agrupa esto en Select, Modify, Joins, Aggregate, Subqueries, DDL, Functions e Indexes para que la sección adecuada esté a un clic.
- Más de 60 consultas SQL prácticas
- 8 categorías desde SELECT hasta índices
- Cubre JOINs, CTEs y funciones ventana
- Sentencias DDL para gestión de tablas
- Copia al portapapeles con un clic
- Sintaxis compatible con PostgreSQL
Gratis. Sin registro. Tus datos permanecen en tu navegador. Anuncios mediante Google AdSense (con consentimiento).
Por Marco B. ·