Menu

SQLite DISTINCT: eliminar duplicados en SELECT

Cómo funciona SELECT DISTINCT en SQLite: una columna, varias columnas, manejo de NULL, COUNT(DISTINCT) y cuándo conviene más usar GROUP BY.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

DISTINCT elimina filas duplicadas

Por defecto, SELECT devuelve todas las filas que coinciden, incluidos los duplicados. Con DISTINCT le indicas a SQLite que agrupe las filas idénticas en las columnas que seleccionaste, de modo que cada combinación única aparezca una sola vez.

Cinco filas entran, tres salen. SQLite revisó la columna customer, descartó los repetidos y devolvió una fila por cada valor único. El orden no está garantizado: si te importa, agrega un ORDER BY.

DISTINCT se aplica a toda la lista del SELECT

Aquí es donde mucha gente se confunde. DISTINCT no elige una sola columna para eliminar duplicados, sino que deduplica filas completas tomando en cuenta todas las columnas que pongas en el SELECT.

Cada combinación única de (customer, country) aparece una sola vez. Si el mismo cliente apareciera con dos países distintos, verías ambas filas: para SQLite no son duplicados.

No existe una sintaxis tipo DISTINCT(customer) que ignore las demás columnas. Los paréntesis se ven tentadores, pero SELECT DISTINCT(customer), country se interpreta igual que SELECT DISTINCT customer, country: los paréntesis solo agrupan una expresión. Si lo que de verdad quieres es una fila por cliente con algún país concreto, eso ya es trabajo de GROUP BY junto con una función de agregación.

COUNT(DISTINCT col) en SQLite

Una necesidad muy habitual: ¿cuántos valores únicos hay en una columna? COUNT(*) cuenta filas, COUNT(col) cuenta valores no nulos, y COUNT(DISTINCT col) cuenta los valores únicos que no son NULL.

Cinco pedidos, tres clientes únicos y tres países únicos. COUNT(DISTINCT ...) es la forma agregada más útil de DISTINCT: la vas a usar siempre que necesites contar "cuántas cosas distintas aparecieron".

Ten en cuenta que SQLite solo permite una única columna dentro de COUNT(DISTINCT ...). Si quieres contar combinaciones únicas de varias columnas, envuélvelas en una subconsulta: SELECT COUNT(*) FROM (SELECT DISTINCT a, b FROM t).

Cómo trata DISTINCT los valores NULL

NULL tiene fama de raro en SQL porque NULL = NULL no se evalúa como TRUE, sino como NULL. Pero DISTINCT hace una excepción especial: a la hora de eliminar duplicados, todos los NULL se consideran iguales entre sí.

Vuelven tres filas: 'ada@example.com', 'dan@example.com' y un único NULL. Los tres correos NULL se fusionaron en uno solo. La misma regla se aplica a GROUP BY y a operaciones de conjuntos como UNION — viene bien recordarlo cuando estés investigando por qué "esa fila NULL aparece una vez en lugar de tres".

DISTINCT se ejecuta antes que ORDER BY y LIMIT

Las cláusulas de un SELECT siguen un orden lógico: FROMWHEREGROUP BYHAVINGSELECT/DISTINCTORDER BYLIMIT. Es decir, DISTINCT primero descarta los duplicados, luego ORDER BY ordena lo que queda y, por último, LIMIT recorta el resultado.

WHERE se queda con cuatro filas, DISTINCT colapsa los duplicados de Boris, ORDER BY los ordena alfabéticamente y LIMIT devuelve los dos primeros. Vale la pena repasar este flujo paso a paso: la confusión sobre el orden de los resultados casi siempre viene de olvidar en qué momento ocurre cada cosa.

DISTINCT vs GROUP BY en SQLite

Si lo único que buscas es eliminar duplicados, estas dos consultas devuelven exactamente las mismas filas:

Mismo resultado. La diferencia está en lo que puedes hacer después:

  • DISTINCT sirve para "dame filas únicas" y nada más.
  • GROUP BY sirve para "agrupa filas y calcula algo por cada grupo" — COUNT(*), SUM(amount), MAX(created_at), etc.

Si te encuentras tirando de DISTINCT y luego te das cuenta de que también quieres un total por cliente, esa es la señal para pasarte a GROUP BY:

Una fila por cliente, con los agregados que querías. DISTINCT no podía hacer esto: no tiene forma de expresar "una fila por grupo más una suma."

Algunos detalles a tener en cuenta

  • Rendimiento. Por lo general, DISTINCT obliga a SQLite a ordenar o hashear las filas para detectar duplicados. En conjuntos de resultados grandes, conviene tener un índice sobre la columna (o columnas) que se deduplican. Y si haces SELECT DISTINCT sobre todas las columnas de una tabla ancha, plantéate si de verdad necesitas todas esas columnas.
  • DISTINCT * casi no se usa. Es válido —SELECT DISTINCT * FROM t deduplica filas completas— pero si tu tabla tiene una clave primaria, cada fila ya es única, así que no aporta nada.
  • No lo confundas con UNIQUE. UNIQUE es una restricción de tabla que impide que se inserten valores duplicados desde el principio. DISTINCT, en cambio, es un filtro en tiempo de consulta que oculta duplicados en el resultado. Herramientas distintas para tareas distintas.

A continuación: expresiones CASE

Cuando ya dominas cómo dar forma a las filas del resultado con SELECT, WHERE, ORDER BY y DISTINCT, el siguiente paso es la lógica condicional dentro de una consulta. Las expresiones CASE te permiten devolver valores distintos según ciertas condiciones: son el equivalente en SQL a una cadena de if/else, y las veremos en la siguiente página.

Preguntas frecuentes

¿Cómo funciona SELECT DISTINCT en SQLite?

SELECT DISTINCT elimina las filas duplicadas del resultado. SQLite compara todas las columnas que aparecen en el SELECT y deja una sola fila por cada combinación única. Se aplica después de WHERE y los JOIN, pero antes de ORDER BY y LIMIT.

¿Puedo usar DISTINCT sobre varias columnas en SQLite?

Sí, pero ten en cuenta que DISTINCT siempre actúa sobre toda la lista del SELECT, no sobre una columna suelta. Por ejemplo, SELECT DISTINCT city, country FROM users devuelve cada par único (city, country). No existe una sintaxis tipo DISTINCT(city) que ignore al resto de columnas; si necesitas eso, recurre a GROUP BY con una función de agregación.

¿Cómo trata DISTINCT los valores NULL en SQLite?

Para deduplicar, DISTINCT considera que un NULL es igual a otro NULL, así que varias filas con NULL se colapsan en una sola. Esto contrasta con el operador = dentro de un WHERE, donde NULL = NULL da resultado desconocido. Es una regla específica de DISTINCT, GROUP BY y UNION.

¿Qué diferencia hay entre DISTINCT y GROUP BY en SQLite?

Si solo quieres deduplicar, SELECT DISTINCT col y SELECT col FROM t GROUP BY col dan exactamente el mismo resultado. La diferencia está en la intención: usa DISTINCT cuando solo te interesan filas únicas, y GROUP BY cuando además vas a calcular agregaciones como COUNT(*) o SUM(amount) por grupo.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR