Saltar al contenido
Aprende SQL con IA: comprueba que un JOIN no duplique tus ventas
Aprender IA

Aprende SQL con IA: comprueba que un JOIN no duplique tus ventas

Aprende SQL con IA y detecta ventas duplicadas por un JOIN. Incluye datos de ejemplo, consultas probadas en SQLite y un prompt para practicar.

Por · Equipo de contenido y revisiónPublicado: 6 min de lectura

Una consulta puede ejecutarse sin errores y producir un total equivocado. Si unes ventas con sus líneas de detalle, cada venta puede aparecer varias veces. Después, un SUM del importe original suma esas repeticiones.

En este tutorial vas a reproducir el fallo, localizarlo y corregirlo. También tienes un prompt para pedir ayuda a una IA sin saltarte la parte importante: entender qué representa cada fila y comprobar los resultados por tu cuenta.

1. Prepara tres ventas y calcula el resultado a mano

Trabaja en una base SQLite nueva y vacía, nunca en producción. Todos los nombres e importes son ficticios. Guarda los importes en céntimos enteros para que este ejercicio sea fácil de comprobar.

La tabla ventas tiene una fila por operación. La tabla lineas registra sus productos. Una venta puede tener varias líneas; dejamos otra sin detalle cargado para comprobar que no desaparezca del informe.

PRAGMA foreign_keys = ON;
CREATE TABLE ventas (
  venta_id INTEGER PRIMARY KEY,
  cliente TEXT NOT NULL,
  total_centimos INTEGER NOT NULL
);
CREATE TABLE lineas (
  linea_id INTEGER PRIMARY KEY,
  venta_id INTEGER NOT NULL REFERENCES ventas(venta_id),
  producto TEXT NOT NULL
);
INSERT INTO ventas VALUES
  (1, 'Ana', 10000),
  (2, 'Ana', 10000),
  (3, 'Beto', 5000);
INSERT INTO lineas VALUES
  (101, 1, 'Cuaderno'),
  (102, 1, 'Lapiz'),
  (103, 2, 'Agenda');

Antes de seguir, apunta tu predicción: tres ventas, 25.000 céntimos y tres líneas. Ana suma 20.000 céntimos en dos ventas; Beto, 5.000 en una. Compartir importe no convierte dos ventas en la misma operación.

Comprueba esa referencia directamente sobre ventas:

SELECT COUNT(*) AS ventas, SUM(total_centimos) AS total_centimos
FROM ventas;

Resultado: ventas = 3; total_centimos = 25000.

2. Ejecuta el JOIN que infla el total

Esta consulta es válida, pero calcula mal los ingresos:

SELECT COUNT(*) AS filas, SUM(v.total_centimos) AS total_centimos
FROM ventas AS v
LEFT JOIN lineas AS l ON l.venta_id = v.venta_id;

Devuelve filas = 4 y total_centimos = 35000. La venta 1 encuentra dos líneas: sus 10.000 céntimos aparecen dos veces. La venta 2 aparece una vez y la venta 3 se conserva sin detalle. El cálculo acaba siendo 10.000 + 10.000 + 10.000 + 5.000.

El cambio está en la unidad de cada fila, también llamada granularidad. Al combinar las tablas, ya no tienes necesariamente una fila por venta. La documentación de SELECT y JOIN en SQLite explica cómo se forman las coincidencias y cómo LEFT JOIN conserva las filas sin correspondencia.

Inspecciona la multiplicación por identificador:

SELECT v.venta_id,
       COUNT(*) AS filas_tras_join,
       COUNT(l.linea_id) AS lineas_reales
FROM ventas AS v
LEFT JOIN lineas AS l ON l.venta_id = v.venta_id
GROUP BY v.venta_id
ORDER BY v.venta_id;

Obtendrás estas ternas: (1, 2, 2), (2, 1, 1) y (3, 1, 0). La última resulta especialmente útil: existe una fila conservada por el JOIN, pero ninguna línea real. COUNT(columna) ignora los valores NULL; COUNT(*) cuenta filas, como recoge la documentación de agregados de SQLite.

3. Pide un diagnóstico que te obligue a aprender

Copia este prompt y añade los bloques anteriores, incluidos los datos:

Estoy aprendiendo SQL con SQLite. Actúa como tutor.
Con estas tablas espero 3 ventas y 25000 céntimos:
Ana: 2 ventas y 20000; Beto: 1 venta y 5000.
Mi LEFT JOIN devuelve 35000.

Primero, pídeme explicar qué representa una fila en cada tabla
y predecir cuántas filas tendrá cada venta después del JOIN.
No me des todavía la consulta corregida.

Después de mi respuesta, señala dónde se multiplica el importe.
Ayúdame a conservar ventas sin líneas y a obtener, por cliente,
el número de ventas, sus ingresos y el número de líneas.
Explica por qué SUM(DISTINCT importe) puede fallar.
Pídeme una prueba independiente y un caso límite adicional.
Usa solo el esquema proporcionado. Si falta una regla de negocio,
pregunta antes de inventarla. Distingue resultados calculados
mentalmente de consultas que realmente hayas ejecutado.

Usa datos sintéticos al practicar. Una respuesta convincente sigue necesitando una ejecución y una comparación con tu referencia. Este prompt es una propuesta didáctica; no representa una prueba comparativa de modelos de IA.

4. Evita el parche SUM(DISTINCT)

Prueba este atajo para ver por qué engaña:

SELECT SUM(DISTINCT v.total_centimos) AS total_centimos
FROM ventas AS v
LEFT JOIN lineas AS l ON l.venta_id = v.venta_id;

El resultado es 15.000. DISTINCT elimina importes repetidos antes de sumarlos, así que conserva únicamente 10.000 y 5.000. Ha eliminado también una venta legítima de Ana. Lo documentado para DISTINCT dentro de agregados es la eliminación de valores duplicados, no la identificación de operaciones.

5. Agrupa el detalle antes de unirlo

Si el informe necesita ingresos y número de líneas, resume primero las líneas a una fila por venta:

WITH lineas_por_venta AS (
  SELECT venta_id, COUNT(*) AS n_lineas
  FROM lineas
  GROUP BY venta_id
)
SELECT v.cliente,
       COUNT(*) AS ventas,
       SUM(v.total_centimos) AS total_centimos,
       SUM(COALESCE(l.n_lineas, 0)) AS lineas
FROM ventas AS v
LEFT JOIN lineas_por_venta AS l ON l.venta_id = v.venta_id
GROUP BY v.cliente
ORDER BY v.cliente;

Resultado esperado y ejecutado:

  • Ana: 2 ventas, 20000 céntimos, 3 líneas
  • Beto: 1 venta, 5000 céntimos, 0 líneas

WITH da nombre al resultado intermedio mediante una CTE. Su alcance es esta sentencia, según la documentación de WITH. Aquí, GROUP BY garantiza una fila por venta en ese resumen. LEFT JOIN mantiene a Beto y COALESCE convierte su ausencia de líneas en cero.

Si únicamente necesitas ingresos por cliente, elimina la unión: la tabla ventas ya contiene lo necesario. Esa consulta sencilla sirve además como comprobación independiente:

SELECT cliente, COUNT(*) AS ventas,
       SUM(total_centimos) AS total_centimos
FROM ventas
GROUP BY cliente
ORDER BY cliente;

Debe coincidir con las tres primeras columnas del informe corregido.

6. Comprueba que la solución resiste cambios

En tu base de práctica, añade otra línea a la primera venta:

INSERT INTO lineas VALUES (104, 1, 'Regla');

Repite ambas consultas. La correcta mantiene 25.000 céntimos y tres ventas; ahora cuenta cuatro líneas. La incorrecta sube a 45.000 céntimos. Puedes explicar el error sin depender de la respuesta de la IA.

Los bloques se ejecutaron el 30 de septiembre de 2026 con SQLite 3.53.1 mediante Python 3.12.14, en una base en memoria, sin conexión a una base externa. Se verificaron los resultados iniciales y esta modificación. PRAGMA es específico de SQLite; para otros motores, adapta la configuración y comprueba el dialecto. No se ejecutaron pruebas en PostgreSQL o MySQL.

Continúa practicando SQL

Antes de confiar en un informe, define qué cuenta cada fila, calcula una referencia y prueba importes iguales y detalles ausentes. Si necesitas reforzar SELECT, filtros y agrupaciones, revisa el temario público de SQL para Principiantes en Cursalo y decide si encaja con tu punto de partida.

Tu siguiente práctica

ChatGPT para Ventas B2B

Investiga cuentas, prepara reuniones y convierte conversaciones en próximos pasos medibles. 6 clases.

Este curso por US$15, en un solo pago. También está incluido en el acceso a toda la escuela.

La matrícula incluye todos los cursos actuales y los nuevos que publiquemos, libros, prompts y materiales. Paga en seis cuotas mensuales de US$20 (US$120 en total) o US$100 en un pago.

02 / LLEVAR A LA PRÁCTICA

Después de leer

Convierte una idea útil en una habilidad repetible.

Elige una ruta breve, aplícala a una tarea real y termina con algo que puedas revisar, usar o compartir.