Manual de campo · trampas de SQL
Unir un histórico contra el catálogo tal como está hoy mide quién sobrevivió, no lo que de verdad pasó: los que desaparecieron son justo los que traían la mala noticia.
Estudios históricos sobre catálogos vivos: universos de activos, clientes activos, productos en catálogo. En general, cualquier «cómo le fue a X» donde X puede haber dejado de existir.
Mal: sólo lo que sigue listado hoy
SELECT h.fecha, avg(h.retorno) AS retorno_medio
FROM historico h
JOIN universo u ON u.simbolo = h.simbolo AND u.activo
GROUP BY h.fecha;
-- los símbolos que quebraron o se deslistaron no están en "universo.activo",
-- así que su mal historial nunca entra al promedio
Bien: el universo tal como era ENTONCES
SELECT h.fecha, avg(h.retorno) AS retorno_medio
FROM historico h
JOIN universo u
ON u.simbolo = h.simbolo
AND h.fecha >= u.alta
AND (u.baja IS NULL OR h.fecha <= u.baja)
GROUP BY h.fecha;
El filtro «activo» describe el catálogo hoy, no el día de cada fila del histórico. La condición correcta es temporal: la fila cuenta si ese símbolo formaba parte del universo en la fecha de esa fila, use el dato alta/baja (o el equivalente) para reconstruir el universo como era entonces, no como quedó después de que los peores casos ya hubieran desaparecido.
Esta trampa —y otras cuatro más— están escondidas en un caso de verdad, con datos de verdad.
Jugar el caso 1 gratis →