Las tablas de TiendaVerde no tienen filas duplicadas: cada una tiene su clave primaria id, así que no hay dos iguales. Y sin embargo, en cuanto proyectas solo una parte de las columnas, empiezan a aparecer repeticiones por todas partes. Preguntar "¿en qué países tengo clientes?" sobre una tabla de quince filas devuelve quince respuestas cuando solo hay tres países distintos. En esta lección aprenderás por qué ocurre, cómo lo resuelve DISTINCT, por qué actúa sobre la combinación completa de columnas del SELECT (el malentendido más habitual del módulo), dónde encaja en el orden lógico de ejecución, y cuándo la aparición de DISTINCT en una consulta es en realidad la señal de que la consulta está mal planteada.
Contenido
- Por qué aparecen filas repetidas
DISTINCTsobre una columnaDISTINCTsobre varias columnas: el malentendido clásico- Dónde encaja
DISTINCTen el orden lógico DISTINCTcombinado conWHEREy conORDER BYCOUNT(DISTINCT columna): un anticipo del módulo 4DISTINCT ON: la extensión de PostgreSQL- El coste de
DISTINCTy cuándo delata un error - Errores Comunes y Consejos
- Ejercicios
- Conclusión
- Por qué aparecen filas repetidas
Empecemos por el problema:
| pais |
|---|
| España |
| España |
| España |
| España |
| España |
| España |
| Portugal |
| Portugal |
| Francia |
| Francia |
| España |
| España |
| España |
| España |
| España |
15 filas. Una por cliente, porque SELECT devuelve una fila de resultado por cada fila de origen. La proyección ha eliminado las columnas que hacían única a cada fila (id, email, nombre...), y lo que queda se repite.
Es importante entender que esto no es un fallo de los datos. En el modelo relacional puro una relación es un conjunto y no admite duplicados, pero SQL no trabaja con conjuntos sino con multiconjuntos (bags): permite repeticiones y solo las elimina si se lo pides explícitamente. Fue una decisión pragmática de los diseñadores del lenguaje: eliminar duplicados cuesta tiempo, y en la mayoría de las consultas no hace falta.
Lo mismo con las ciudades:
Devuelve 15 filas con Valencia cuatro veces y Barcelona dos.
DISTINCT sobre una columna
DISTINCT sobre una columnaLa palabra clave DISTINCT se escribe inmediatamente después de SELECT y elimina las filas repetidas del resultado:
| pais |
|---|
| España |
| Portugal |
| Francia |
3 filas. Ahora sí has respondido a la pregunta "¿en qué países tengo clientes?".
| ciudad |
|---|
| Valencia |
| Castellón |
| Madrid |
| Barcelona |
| Lisboa |
| Oporto |
| Lyon |
| París |
| Alicante |
| Sevilla |
| Zaragoza |
11 filas de las 15: Valencia aparecía 4 veces y Barcelona 2.
Otro caso útil: saber qué métodos de pago se usan realmente. La restricción CHECK de la tabla admite cuatro, pero ¿se usan todos?
| metodo_pago |
|---|
| tarjeta |
| transferencia |
| paypal |
| contrareembolso |
Los cuatro. Y los estados:
| estado |
|---|
| entregado |
| enviado |
| pagado |
| pendiente |
| cancelado |
Los cinco valores del dominio están representados.
Muy importante:
DISTINCTno ordena. Los resultados de arriba salen en un orden que PostgreSQL elige según cómo haya eliminado los duplicados (normalmente con una tabla hash, cuyo orden es impredecible). Podrías verFrancia, España, Portugalperfectamente. Si quieres un orden concreto,ORDER BY(sección 5).
Dos detalles de sintaxis:
DISTINCTafecta a toda la lista de columnas, no a la que tiene al lado.SELECT DISTINCT pais, ciudadno es "el pais distinto y la ciudad": es la sección 3.DISTINCT(pais)funciona, pero es engañoso: esos paréntesis son los de una expresión, no los de una función.SELECT DISTINCT (pais), ciudadsigue aplicandoDISTINCTa las dos columnas. No escribasDISTINCTcon paréntesis; induce a error a quien lo lea.
Y un apunte sobre nulos: para DISTINCT, todos los NULL cuentan como un mismo valor y se colapsan en una sola fila. Es una excepción deliberada a la regla de que NULL no es igual a NULL, y la verás en el ejercicio 3.
DISTINCT sobre varias columnas: el malentendido clásico
DISTINCT sobre varias columnas: el malentendido clásicoEsta es la parte que hay que interiorizar bien:
| pais | ciudad |
|---|---|
| España | Valencia |
| España | Castellón |
| España | Madrid |
| España | Barcelona |
| España | Alicante |
| España | Sevilla |
| España | Zaragoza |
| Portugal | Lisboa |
| Portugal | Oporto |
| Francia | Lyon |
| Francia | París |
11 filas, y España aparece siete veces. ¿No habíamos dicho que DISTINCT elimina duplicados?
Los ha eliminado. Lo que ocurre es que DISTINCT compara la fila completa, no columna por columna. (España, Valencia) y (España, Madrid) son dos filas distintas, aunque compartan el primer valor. Solo se elimina una fila si todos sus valores coinciden con los de otra: (España, Valencia) aparecía cuatro veces en la tabla y ha quedado una.
| Lo que mucha gente cree que hace | Lo que hace de verdad |
|---|---|
"Un valor distinto de pais, y para cada uno la ciudad" |
Cada combinación distinta de (pais, ciudad) |
| Debería devolver 3 filas | Devuelve 11 |
Piénsalo así: DISTINCT mira la fila del resultado como si fuera una tupla y se pregunta "¿he visto ya exactamente esta tupla?".
Otro ejemplo, esta vez sobre el catálogo: ¿qué combinaciones de categoría y proveedor existen?
Con ORDER BY para poder leerlo (lo justificamos en la sección 5):
| categoria_id | proveedor_id |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
| 2 | 4 |
| 3 | 3 |
| 3 | 5 |
| 4 | 1 |
| 4 | 2 |
| 4 | 3 |
| 5 | 4 |
| 5 | 5 |
| 6 | 5 |
12 combinaciones a partir de 20 productos. Se lee mucha información de negocio en esa tabla: la categoría 4 (Bebidas) se surte de tres proveedores distintos, mientras que la 6 (Complementos) depende de uno solo, y ese único proveedor —el 5, EcoNordic— es precisamente el que está inactivo. Sin DISTINCT habrías tenido que leer 20 filas para llegar a la misma conclusión.
Si de verdad quieres "un país por fila y algo de sus ciudades", DISTINCT no es la herramienta: necesitas agrupar, que es GROUP BY (lección 04-05). La diferencia conceptual, para tenerla clara desde ya:
| Herramienta | Qué hace | Lección |
|---|---|---|
DISTINCT |
Elimina filas repetidas del resultado tal cual está | 02-04 |
GROUP BY |
Colapsa grupos de filas en una sola y permite calcular sobre cada grupo (contar, sumar, promediar) | 04-05 |
- Dónde encaja
DISTINCT en el orden lógico
DISTINCT en el orden lógicoDISTINCT se aplica después de la proyección del SELECT y antes de ORDER BY. Esto es coherente: solo se pueden comparar filas duplicadas una vez que se sabe qué columnas contienen.
flowchart LR
A["1 · FROM<br/>clientes<br/>15 filas"] --> B["2 · WHERE<br/>filtra filas"]
B --> C["3 · SELECT<br/>proyecta pais, ciudad"]
C --> D["3b · DISTINCT<br/>elimina duplicados<br/>11 filas"]
D --> E["4 · ORDER BY"]
E --> F["5 · LIMIT"]
De ahí se deducen dos reglas que verás en acción enseguida:
| Regla | Consecuencia |
|---|---|
WHERE se ejecuta antes que DISTINCT |
Primero se filtra, luego se deduplica. Nunca al revés |
ORDER BY se ejecuta después que DISTINCT |
Solo puedes ordenar por columnas que hayan sobrevivido a la proyección |
DISTINCT combinado con WHERE y con ORDER BY
DISTINCT combinado con WHERE y con ORDER BY5.1. Con WHERE
| ciudad |
|---|
| Valencia |
| Castellón |
| Madrid |
| Barcelona |
| Alicante |
| Sevilla |
| Zaragoza |
7 ciudades españolas. El orden es: FROM trae las 15 filas → WHERE deja 11 → SELECT proyecta ciudad → DISTINCT reduce a 7.
5.2. Con ORDER BY
| pais |
|---|
| España |
| Francia |
| Portugal |
Ahora el orden sí está garantizado (alfabético). ORDER BY es la lección siguiente; aquí lo usamos solo para hacer legibles los resultados.
5.3. La restricción: solo puedes ordenar por lo que hayas seleccionado
Prueba esto:
ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
LINE 3: ORDER BY ciudad;
^El mensaje es explícito y la razón es lógica, no arbitraria. Después del DISTINCT solo quedan tres filas: España, Portugal y Francia. La fila España procede de once filas originales con once ciudades distintas. ¿Por cuál de las once habría que ordenarla? La pregunta no tiene respuesta, así que PostgreSQL se niega a inventarse una.
La regla, memorizable: con SELECT DISTINCT, todo lo que aparezca en ORDER BY debe aparecer también en la lista del SELECT.
Si lo que querías era ordenar los países por algún criterio derivado de las ciudades, necesitas GROUP BY y una función de agregación (módulo 4).
Un caso frecuente que también falla por esto: ordenar por una columna que no proyectas.
Mismo mensaje. Y si la "arreglas" añadiendo precio al SELECT, cambias la pregunta: pasarías de "categorías distintas" (6 filas) a "combinaciones distintas de categoría y precio" (20 filas, porque casi todos los precios son únicos). Añadir columnas al SELECT debilita el DISTINCT.
COUNT(DISTINCT columna): un anticipo del módulo 4
COUNT(DISTINCT columna): un anticipo del módulo 4Muchas veces no quieres la lista de valores distintos, sino cuántos hay. Para eso se combina DISTINCT con la función de agregación COUNT:
SELECT COUNT(*) AS filas,
COUNT(ciudad) AS ciudades_no_nulas,
COUNT(DISTINCT ciudad) AS ciudades_distintas,
COUNT(DISTINCT pais) AS paises_distintos
FROM clientes;| filas | ciudades_no_nulas | ciudades_distintas | paises_distintos |
|---|---|---|---|
| 15 | 15 | 11 | 3 |
Fíjate en la diferencia entre las tres variantes de COUNT:
| Expresión | Qué cuenta |
|---|---|
COUNT(*) |
Filas, sin mirar valores |
COUNT(columna) |
Valores no nulos de esa columna |
COUNT(DISTINCT columna) |
Valores distintos y no nulos |
Aquí COUNT(ciudad) coincide con COUNT(*) porque en TiendaVerde ningún cliente tiene la ciudad a nulo, pero la columna admite nulos y en otra base de datos la diferencia sería visible.
No profundizamos más: COUNT, SUM, AVG, MIN y MAX son la lección 04-04, y la agrupación por categorías, la 04-05. Lo dejamos aquí simplemente porque es la aplicación más frecuente de DISTINCT en el trabajo real de análisis.
DISTINCT ON: la extensión de PostgreSQL
DISTINCT ON: la extensión de PostgreSQLPostgreSQL añade una variante que no está en el estándar SQL y que es enormemente útil: DISTINCT ON (columnas) conserva la primera fila de cada grupo de valores, según el orden que tú indiques.
Problema: el producto más caro de cada categoría.
SELECT DISTINCT ON (categoria_id)
categoria_id,
id,
nombre,
precio
FROM productos
ORDER BY categoria_id, precio DESC;| categoria_id | id | nombre | precio |
|---|---|---|---|
| 1 | 1 | Aceite de oliva virgen extra 500 ml | 12.50 |
| 2 | 6 | Crema facial de aloe vera 50 ml | 18.90 |
| 3 | 13 | Velas de cera de soja (pack 2) | 13.75 |
| 4 | 15 | Té verde matcha ceremonial 30 g | 22.00 |
| 5 | 19 | Desodorante natural en barra 50 g | 7.80 |
| 6 | 20 | Cápsulas de espirulina 120 uds | 16.40 |
Seis filas, una por categoría, con el producto más caro de cada una. Esto con DISTINCT a secas es imposible.
Cómo funciona, paso a paso:
ORDER BY categoria_id, precio DESCordena todas las filas: primero agrupadas por categoría, y dentro de cada categoría, de más caro a más barato.DISTINCT ON (categoria_id)recorre ese resultado ordenado y se queda con la primera fila de cada valor decategoria_id, descartando el resto.
De ahí sale la regla de oro:
Las columnas de
DISTINCT ON (...)deben ser las primeras delORDER BY, y en el mismo orden. Si no lo son, PostgreSQL da error; y si elORDER BYno desempata bien lo que viene después, la fila elegida dentro de cada grupo es impredecible.
Si cambias precio DESC por precio, obtienes el producto más barato de cada categoría:
SELECT DISTINCT ON (categoria_id)
categoria_id, id, nombre, precio
FROM productos
ORDER BY categoria_id, precio;| categoria_id | id | nombre | precio |
|---|---|---|---|
| 1 | 5 | Tomate triturado ecológico 400 g | 1.95 |
| 2 | 9 | Bálsamo labial de caléndula 15 ml | 4.60 |
| 3 | 11 | Estropajo vegetal de luffa (pack 3) | 5.50 |
| 4 | 14 | Infusión de manzanilla ecológica 20 uds | 3.25 |
| 5 | 18 | Cepillo de dientes de bambú | 3.50 |
| 6 | 20 | Cápsulas de espirulina 120 uds | 16.40 |
El patrón "la fila más X de cada grupo" (el último pedido de cada cliente, la reseña más reciente de cada producto, el precio más alto de cada categoría) es uno de los más pedidos en el mundo real, y DISTINCT ON lo resuelve en tres líneas.
Portabilidad:
| Motor | Cómo se hace |
|---|---|
| PostgreSQL | DISTINCT ON (...) con el ORDER BY adecuado |
| Estándar SQL / MySQL 8 / SQL Server / Oracle | Función de ventana: ROW_NUMBER() OVER (PARTITION BY categoria_id ORDER BY precio DESC) y quedarse con la fila 1 |
| SQLite | Función de ventana (desde 3.25) o el truco de MAX() con GROUP BY |
| MySQL 5.7 | Subconsulta correlacionada (módulo 7) |
La forma portable con funciones de ventana se estudia en la lección 10-03, y es la que deberás usar si tu SQL tiene que funcionar fuera de PostgreSQL. Mientras trabajes con PostgreSQL, DISTINCT ON es más corto y suele ser más rápido.
- El coste de
DISTINCT y cuándo delata un error
DISTINCT y cuándo delata un errorDISTINCT no es gratis. Para saber si una fila está repetida, PostgreSQL tiene que comparar todas las filas entre sí, y lo hace de una de estas dos formas:
| Estrategia | Cómo funciona | Coste |
|---|---|---|
HashAggregate |
Construye una tabla hash con las filas ya vistas | Rápida, pero consume memoria proporcional al número de valores distintos |
Sort + Unique |
Ordena todas las filas y elimina las contiguas iguales | Requiere ordenar todo el conjunto; si no cabe en memoria, escribe en disco |
Con 15 filas es instantáneo. Con diez millones de filas y una columna de texto largo, un DISTINCT innecesario puede convertir una consulta de 50 ms en una de 30 segundos. Podrás verlo tú mismo con EXPLAIN en el módulo 8.
Y hay algo más importante que el coste: un DISTINCT inesperado suele ser el síntoma de una consulta mal planteada, no la solución. El caso típico llega en el módulo 3:
-- Anticipo del módulo 3: "clientes que han hecho algún pedido"
SELECT c.nombre, c.apellidos
FROM clientes AS c
JOIN pedidos AS p ON p.cliente_id = c.id;Esa consulta devuelve 20 filas y no 12, porque Lucía Martínez tiene tres pedidos (1, 5 y 15) y aparece tres veces. El reflejo natural es añadir DISTINCT y quedarse tranquilo. Pero el DISTINCT no arregla nada: oculta el hecho de que la unión ha multiplicado las filas. Si mañana añades una columna al SELECT —por ejemplo p.fecha_pedido—, las filas vuelven a duplicarse y el DISTINCT deja de servir.
La lista de comprobación cuando te descubras escribiendo DISTINCT:
- ¿Hay duplicados de verdad, o los está creando mi consulta? Si es lo segundo, el problema está en la unión, no en la proyección.
- ¿Lo que quiero es "valores distintos" o "un resultado por grupo"? Si es lo segundo, es
GROUP BY(04-05) oDISTINCT ON(sección 7). - ¿Quiero comprobar existencia? Entonces la herramienta correcta es
EXISTS(lección 07-03), que no multiplica filas y por tanto no necesita deduplicar. - ¿Estoy deduplicando por columnas que no necesito? Quitar del
SELECTuna columna innecesaria puede hacer que elDISTINCTsobre.
DISTINCT es perfectamente legítimo para lo que hemos hecho en esta lección: preguntar "¿qué valores distintos hay en esta columna?". Lo sospechoso es usarlo como parche.
Errores Comunes y Consejos
- Creer que
DISTINCT columna1, columna2deduplica solo por la primera. Deduplica por la combinación completa. Es el malentendido número uno. - Escribir
DISTINCT(columna). Funciona, pero hace pensar queDISTINCTes una función que se aplica a esa columna. No lo es. EscribeDISTINCT columna1, columna2. - Esperar que
DISTINCTordene. No ordena. Si necesitas orden,ORDER BY. - Ordenar por una columna que no está en un
SELECT DISTINCT.ORDER BY expressions must appear in select list. Y "arreglarlo" añadiendo la columna cambia la pregunta. - Añadir columnas y no darse cuenta de que el
DISTINCTdeja de servir. Cada columna nueva puede multiplicar las filas del resultado. - Usar
DISTINCTpara tapar duplicados creados por unJOIN. Corrige la consulta, no el síntoma. - Olvidar que los
NULLse agrupan.DISTINCTdevuelve una sola fila conNULL, aunque haya cien. - Usar
DISTINCT ONsin elORDER BYcorrecto. La fila que se conserva de cada grupo es entonces impredecible: hoy una, mañana otra. - Consejo: para contar valores únicos,
COUNT(DISTINCT col)en lugar de traerte la lista y contarla a mano. - Consejo: usa
DISTINCTcomo herramienta de exploración.SELECT DISTINCT estado FROM pedidos;es la forma más rápida de saber qué valores contiene realmente una columna, incluidos los que no deberían estar ahí. - Consejo: si
DISTINCTes lento, mira el plan.EXPLAIN(módulo 8) te dirá si está ordenando en disco.
Ejercicios
Ejercicio 1
Marketing quiere saber desde qué ciudades se ha comprado en Portugal y Francia. Escribe una consulta que devuelva las combinaciones distintas de pais y ciudad de los clientes que no sean de España, ordenadas por país y ciudad. Explica por qué el resultado tiene el número de filas que tiene.
Ejercicio 2
Un compañero escribe esta consulta para saber cuántos métodos de pago distintos se usan y se sorprende del resultado:
Explica qué devuelve realmente, cuántas filas y por qué no responde a su pregunta. Escribe después las dos consultas correctas: la que da la lista de métodos y la que da el número.
Ejercicio 3
Usando DISTINCT ON, obtén el pedido más reciente de cada cliente que haya comprado: cliente_id, id del pedido, fecha_pedido y estado. Explica por qué el resultado tiene 12 filas y no 15, y qué papel juega el ORDER BY.
Soluciones
Solución 1
| pais | ciudad |
|---|---|
| Francia | Lyon |
| Francia | París |
| Portugal | Lisboa |
| Portugal | Oporto |
4 filas. El razonamiento sigue el orden lógico de ejecución:
FROM clientes→ 15 filas.WHERE pais <> 'España'→ quedan 4 (los clientes 7, 8, 9 y 10). Aquí no hay problema de nulos porquepaisesNOT NULL; si admitiera nulos, esos clientes se habrían perdido silenciosamente, como viste en 02-03.SELECT pais, ciudad→ proyecta dos columnas de esas 4 filas.DISTINCT→ busca combinaciones repetidas... y no hay ninguna, porque los cuatro clientes extranjeros viven en cuatro ciudades diferentes.
Es decir, en este caso concreto DISTINCT no elimina nada. Eso no lo hace inútil: garantiza que si mañana se registra un segundo cliente en Lisboa, el informe seguirá siendo correcto.
Solución 2
La consulta del compañero devuelve las combinaciones distintas de método de pago y estado:
| metodo_pago | estado |
|---|---|
| tarjeta | entregado |
| tarjeta | cancelado |
| tarjeta | enviado |
| tarjeta | pagado |
| transferencia | entregado |
| transferencia | pagado |
| paypal | entregado |
| paypal | enviado |
| contrareembolso | entregado |
| contrareembolso | pendiente |
10 filas. tarjeta aparece cuatro veces, una por cada estado en el que hay algún pedido pagado con tarjeta. No responde a "cuántos métodos de pago distintos hay" porque DISTINCT deduplica la pareja completa, y las parejas son distintas aunque compartan el método.
Las dos consultas correctas:
| metodo_pago |
|---|
| contrareembolso |
| paypal |
| tarjeta |
| transferencia |
| metodos_usados |
|---|
| 4 |
La moraleja: cada columna que añades al SELECT puede multiplicar las filas del resultado, porque debilita la condición de igualdad que usa DISTINCT. Antes de añadir una columna a un SELECT DISTINCT, pregúntate si sigue respondiendo a tu pregunta.
Solución 3
SELECT DISTINCT ON (cliente_id)
cliente_id,
id,
fecha_pedido,
estado
FROM pedidos
ORDER BY cliente_id, fecha_pedido DESC;| cliente_id | id | fecha_pedido | estado |
|---|---|---|---|
| 1 | 15 | 2025-12-02 | entregado |
| 2 | 11 | 2025-09-09 | entregado |
| 3 | 3 | 2025-04-02 | entregado |
| 4 | 16 | 2025-12-19 | enviado |
| 5 | 18 | 2026-01-27 | pagado |
| 6 | 19 | 2026-02-09 | pagado |
| 7 | 17 | 2026-01-13 | enviado |
| 8 | 9 | 2025-07-15 | entregado |
| 9 | 20 | 2026-02-21 | pendiente |
| 10 | 12 | 2025-10-01 | entregado |
| 11 | 13 | 2025-10-22 | entregado |
| 12 | 14 | 2025-11-14 | entregado |
12 filas y no 15. El motivo está en los huecos deliberados del conjunto de datos: los clientes 13, 14 y 15 no han hecho ningún pedido, así que no aparecen en la tabla pedidos y no hay nada que agrupar para ellos. Una consulta sobre pedidos solo puede hablar de clientes que han pedido; para listar también a los que nunca compraron hace falta combinar las dos tablas con un LEFT JOIN, que es exactamente el contenido de la lección 03-03.
El papel del ORDER BY es doble y ambos son imprescindibles:
cliente_idprimero porque es la columna delDISTINCT ON: PostgreSQL exige que coincidan, ya que necesita las filas de cada cliente juntas para quedarse con una.fecha_pedido DESCdespués porque determina cuál de las filas de cada cliente sobrevive: la primera del grupo, es decir, la de fecha más alta.
Si escribieras ORDER BY cliente_id, fecha_pedido (ascendente), obtendrías el primer pedido de cada cliente. Y si omitieras la segunda columna del ORDER BY, la fila elegida dentro de cada cliente sería la que el motor devolviera primero, que puede cambiar entre ejecuciones.
Comprobación rápida: Lucía Martínez (cliente 1) tiene los pedidos 1, 5 y 15, con fechas 2025-03-04, 2025-05-07 y 2025-12-02. Ha salido el 15, el más reciente. Correcto.
Conclusión
Ya sabes tratar los duplicados:
- Las filas repetidas no vienen de los datos, sino de la proyección: al quitar columnas, lo que queda se repite. SQL trabaja con multiconjuntos y no las elimina si no se lo pides.
DISTINCTse escribe justo después deSELECTy elimina filas repetidas comparando la combinación completa de columnas proyectadas, no solo la primera.- Se aplica después de la proyección y antes de
ORDER BY, de donde sale la restricción de que todo lo que ordenes debe estar en elSELECT. - Los
NULLse colapsan en una sola fila, por excepción a la regla general de los nulos. COUNT(DISTINCT columna)cuenta valores únicos y es la aplicación más habitual en análisis de datos; las agregaciones completas llegan en el módulo 4.DISTINCT ON (...)es una extensión de PostgreSQL que devuelve la primera fila de cada grupo según elORDER BY, y resuelve en tres líneas el patrón "la fila más reciente / más cara de cada X". Fuera de PostgreSQL se hace con funciones de ventana (módulo 10).DISTINCTcuesta (ordenar o construir una tabla hash) y, cuando aparece por sorpresa, suele delatar una consulta mal planteada más que resolver un problema.
En la siguiente lección, Ordenando datos con ORDER BY, dejarás de aceptar el orden que el motor tenga a bien darte. Verás cómo ordenar por una o varias columnas, cómo se resuelven los empates, cómo ordenar por alias y por expresiones calculadas, dónde coloca PostgreSQL los valores nulos (y por qué MySQL los pone en el otro extremo) y por qué la letra Ñ puede aparecer donde no esperas.
Curso de SQL
Módulo 1: Introducción a SQL
- ¿Qué es SQL?
- Configurando tu entorno SQL
- Sintaxis básica de SQL
- Entendiendo bases de datos y tablas
- El modelo relacional: claves primarias y foráneas
- La base de datos del curso: TiendaVerde
Módulo 2: Consultas básicas de SQL
- Instrucción SELECT
- Alias, expresiones y columnas calculadas
- Filtrando datos con WHERE
- DISTINCT y eliminación de duplicados
- Ordenando datos con ORDER BY
- Limitando resultados con LIMIT
Módulo 3: Trabajando con múltiples tablas
- Operaciones JOIN
- INNER JOIN
- LEFT JOIN
- RIGHT JOIN
- FULL OUTER JOIN
- SELF JOIN y CROSS JOIN
- Uniones de conjuntos: UNION, INTERSECT y EXCEPT
Módulo 4: Filtrado avanzado de datos
- Usando LIKE para coincidencia de patrones
- Operadores IN y BETWEEN
- Valores NULL y IS NULL
- Funciones de agregación: COUNT, SUM, AVG, MIN y MAX
- Agregando datos con GROUP BY
- Cláusula HAVING
Módulo 5: Manipulación de datos
- Creando tablas y restricciones con CREATE TABLE
- Instrucción INSERT
- Instrucción UPDATE
- Instrucción DELETE
- Instrucción UPSERT (MERGE)
- Modificando el esquema: ALTER TABLE y migraciones seguras
Módulo 6: Funciones avanzadas de SQL
- Funciones de cadena
- Funciones numéricas
- Funciones de fecha y hora
- Conversión de tipos y manejo de NULL: CAST y COALESCE
- Expresiones condicionales
Módulo 7: Subconsultas y consultas anidadas
- Introducción a subconsultas
- Subconsultas correlacionadas
- EXISTS y NOT EXISTS
- Usando subconsultas en cláusulas SELECT, FROM y WHERE
- Subconsultas o JOIN: cuál elegir
Módulo 8: Índices y optimización de rendimiento
- Entendiendo los índices
- Creación y gestión de índices
- Tipos de índice y cuándo no indexar
- Técnicas de optimización de consultas
- Análisis del rendimiento de consultas
Módulo 9: Transacciones y concurrencia
- Introducción a las transacciones
- Propiedades ACID
- Instrucciones de control de transacciones
- Niveles de aislamiento y anomalías de concurrencia
- Manejo de concurrencia: bloqueos e interbloqueos
Módulo 10: Temas avanzados
- Vistas
- Expresiones de tabla comunes (CTE)
- Funciones de ventana
- Procedimientos almacenados
- Triggers
- JSON y datos semiestructurados
Módulo 11: SQL en la práctica
- Casos de uso en el mundo real
- Mejores prácticas
- Seguridad: inyección SQL, permisos y roles
- SQL para análisis de datos
- SQL en desarrollo web
