lección 4
Día 2 (tarde) — El LTV del anual y la renovación global
Con los datos ya limpios, pasas a SQL para calcular los KPIs de superficie: el reparto de planes, el LTV por plan (que confirma el titular de Rubén), la tasa de renovación global (que parece sana) y el hueco de los que pagan pero no vienen. Aquí aprendes a derivar la renovación encadenando suscripciones con un self-join.
⏱ 55 min
### ¿Por qué ahora SQL, si venías limpiando en Pandas?
Llevas dos días en Pandas y de repente cambias a SQL. ¿Capricho? No: es cómo se trabaja de verdad. La exploración y la limpieza —abrir los CSV crudos, ver qué viene sucio, decidir qué hacer con cada mancha— es terreno de Pandas, porque es un trabajo de tanteo, celda a celda, donde quieres ver y tocar. Pero el análisis —los números que van a acabar en un panel, las tasas que le enseñarás a Marta— se produce en SQL, contra las tablas ya limpias, porque así trabaja el equipo de VueltaFit y porque es el idioma en el que se piden y se comprueban las cifras de negocio. Dicho de otra forma: la limpieza es la cocina y el análisis es el emplatado, y el emplatado se hace en SQL. Las siete tablas que vas a consultar ya están limpias —el plan unificado, las fechas convertidas, los check-ins deduplicados, los importes en número—, así que puedes concentrarte en las preguntas, no en las manchas.
Ya sabes escribir SQL de tus encargos anteriores: SELECT para elegir columnas, WHERE para filtrar, GROUP BY para agrupar, JOIN para cruzar tablas. Hoy usarás todo eso y aprenderás una pieza nueva que es la que resuelve la renovación: el self-join, que es cruzar una tabla consigo misma para comparar unas filas con otras. Suena raro la primera vez —¿para qué cruzo una tabla consigo misma?—, pero es exactamente lo que hace falta para preguntar «¿este socio, después de que le venciera esta suscripción, arrancó otra?»: comparas cada suscripción con las demás suscripciones del mismo socio. Es la herramienta con la que hoy conviertes en número la definición de «renovar» que decidiste ayer.
### El LTV: una idea vieja con un nombre nuevo
Empecemos por el número que Rubén quiere y que cree que le da la razón: el LTV, el valor de un cliente a lo largo de su vida. La idea es más vieja que el término. Los tenderos de toda la vida sabían, sin llamarlo así, que un cliente fiel que viene cada semana durante veinte años vale muchísimo más que uno que entra una vez y no vuelve, y trataban distinto a uno y a otro. Lo que hizo el marketing moderno fue ponerle número: el LTV es cuánto dinero deja un cliente en total desde que se hace cliente hasta que se va. En un negocio de suscripción se calcula sumando todo lo que ha pagado cada cliente. Y aquí está la trampa que vas a destapar esta semana, aunque hoy todavía le des la razón a Rubén: el LTV mide lo pagado, no lo fiel que es el cliente, y en un plan de prepago esas dos cosas se separan.
Piénsalo con las dos formas de pagar. El socio mensual paga unos 39 € cada mes: su LTV va subiendo poco a poco, mes a mes, y si se va a los cuatro meses su LTV se queda en unos 156 €. El socio anual paga los doce meses de golpe por adelantado —unos 449 € por el año— el día que se da de alta: su LTV salta a 449 € de entrada, aunque deje de venir en febrero. Así que cuando calcules el LTV medio por plan, el anual saldrá muy por encima —en torno a los 460 € frente a unos 300 € del mensual, alrededor de un 55% más—, y Rubén dirá «¿ves? El anual es oro». Y tendrá razón en el dato y se equivocará en la conclusión, porque ese LTV alto no es fidelidad: es el calendario de cobro. El anual ha pagado más porque pagó por adelantado, no porque se quede más. Hoy calculas ese LTV y se lo confirmas, tal cual. La grieta llega después.
### Derivar la renovación: el self-join
Ahora la pieza central. Ayer definiste que una suscripción vencida renueva si el mismo socio arranca otra dentro de los treinta días siguientes a su fin. Toca convertirlo en SQL. La técnica es el self-join, o su primo el subconsulta con EXISTS: para cada suscripción vencida, preguntas si existe otra suscripción, del mismo socio y distinta de ella, cuya fecha de inicio caiga entre el fin de la primera y treinta días después. Si existe, renovó; si no, se fue. En SQL eso se escribe con EXISTS, que devuelve verdadero o falso según si la subconsulta encuentra al menos una fila. Es la traducción literal de la pregunta «¿hay otra suscripción suya que empiece justo cuando esta acaba?».
Cuando calcules la renovación global sobre todas las suscripciones ya vencidas —las que su fin es anterior al 30 de junio de 2024, la fecha en que se extrajeron los datos—, saldrá alrededor del 52%. Poco más de la mitad renueva. Y esto es importante para la historia de la semana: ese 52% global tiene una pinta perfectamente sana. En gimnasios, retener a la mitad de los socios de un periodo al siguiente no es ningún escándalo; muchas cadenas estarían encantadas. Por eso nadie ha sospechado nada mirando el total. La renovación global es el número que tranquiliza a todo el mundo y que hace que la campaña de Rubén parezca una buena idea inocente. La historia, como casi siempre, no está en el total: está en cuanto ese total se parte en trozos. Pero eso es mañana. Hoy calculas el total, y parece que todo va bien.
### Pagar no es venir: el hueco que hay que medir
La última cifra de hoy es la que enlaza con el jueves, aunque hoy solo la dejes anotada. Recuerda la costura del lunes: recepción cuenta como activo a quien paga, operaciones a quien viene, y entre las dos definiciones hay un hueco. Toca medirlo. Un socio «que paga» es el que tiene una suscripción con estado activa. Un socio «que viene» es, además, el que ha cruzado el torniquete en las últimas cuatro semanas. La diferencia entre esos dos números —los que pagan pero no vienen— ronda los 1.200 socios. Mil doscientas personas que tienen la cuota al día y no pisan el gimnasio desde hace más de un mes. Hoy no los explicas; solo los cuentas y anotas que están ahí. Nuria te lo dirá: «guárdate ese hueco, que es importante, y fíjate si mañana son más de un plan que de otro». Lo son, pero eso es la historia del jueves.
Cuidado con el denominador de una tasa: es tan importante como el numerador, y es lo primero que hay que escribir al lado. La renovación global no es «renovaciones entre todas las suscripciones»: es «renovaciones entre las suscripciones que YA HAN VENCIDO». Una suscripción cuyo fin todavía no ha llegado no ha tenido ocasión de renovar, así que meterla en el denominador hundiría la tasa artificialmente. Definir el denominador —«vencidas a 30 de junio»— es parte de definir la métrica, no un detalle técnico. Una tasa sin su denominador escrito al lado no es un número, es una opinión con decimales.
### El filtro define de quién hablas
El WHERE de una consulta parece humilde —solo filtra filas— pero es una de las decisiones más importantes que tomas, porque define la población de la que hablas, y esa definición cambia el resultado tanto como cualquier cálculo. Cuando calculas la renovación solo sobre las suscripciones ya vencidas (filtrando con WHERE las que su fin es anterior a la fecha de extracción), el filtro no es un tecnicismo: es lo que hace que la tasa signifique «de las que pudieron renovar, cuántas lo hicieron». Cuando cuentas los pagos solo en estado ok, el filtro decide que los reembolsos no cuentan como valor. Cada WHERE es una frase que empieza por «de entre...», y esa frase es la mitad del significado de tu número. Por eso, al lado de cada tasa que entregues, conviene poder decir en voz alta a qué población se aplica: no es lo mismo «el 41% de las suscripciones anuales renueva» que «el 41% de las suscripciones anuales vencidas renueva», y la segunda es la verdadera.
Hay una consecuencia de esto que separa a los analistas cuidadosos del resto: dos personas pueden calcular «la renovación del anual» y sacar números distintos, no porque una se equivoque, sino porque han filtrado poblaciones distintas. Una cuenta sobre todas las suscripciones anuales, otra solo sobre las vencidas, otra solo sobre las de socios que siguen activos. Ninguna miente; están respondiendo preguntas ligeramente distintas sin darse cuenta. Por eso, cuando dos cifras que deberían coincidir no coinciden, lo primero que hay que comparar no es el cálculo, es el filtro: casi siempre el desacuerdo está en un WHERE distinto, en una población definida de otra forma. Escribir el filtro de forma explícita y decirlo al entregar la cifra evita esas discusiones estériles donde nadie tiene razón porque cada uno habla de una población distinta.
Consejo de senior: cuando dos personas discutan sobre un número que no cuadra, la pregunta que zanja el 90% de esas discusiones es «¿sobre qué filas lo has calculado exactamente?». No sobre el cálculo, sobre la población. La mayoría de los desacuerdos entre analistas no son errores de aritmética: son dos WHERE distintos que nadie ha puesto sobre la mesa. Uno contaba los reembolsos, el otro no; uno incluía las suscripciones aún vivas, el otro solo las vencidas. Hacer explícito el filtro —«de entre estas filas»— antes de comparar cifras ahorra reuniones enteras de gente teniendo razón a la vez sobre cosas distintas.
### Las funciones de agregación: contar, sumar, promediar
El corazón de casi toda pregunta de negocio en SQL es una función de agregación: una operación que toma muchas filas y las resume en un número. Las cuatro que usarás sin parar son COUNT (cuántas filas hay), SUM (la suma de una columna), AVG (el promedio) y, combinadas con GROUP BY, calculan ese número por cada grupo. «¿Cuántos socios por sede?» es COUNT agrupado por sede. «¿LTV medio por plan?» es AVG de la suma por socio, agrupado por plan. «¿Cuántas suscripciones vencidas?» es COUNT con un filtro. Toda la analítica descriptiva —la que describe qué hay— se construye con estas piezas: agrupar por una dimensión y agregar una medida. Dominar las agregaciones no es saber más funciones; es entender que casi cualquier pregunta de negocio tiene la forma «para cada X, ¿cuánto/cuántos Y?», y esa forma se traduce directa a un GROUP BY con una agregación.
Hay dos sutilezas de las agregaciones que conviene tener claras porque son fuente de errores. La primera: COUNT(*) cuenta filas, pero COUNT(columna) cuenta solo las filas donde esa columna no es nula, y COUNT(DISTINCT columna) cuenta valores distintos. Confundirlos cambia el número: «cuántos check-ins» (filas) no es «cuántos socios distintos vinieron» (DISTINCT socio). La segunda: cuando promedias, cuidado con qué estás promediando. El LTV medio no se calcula promediando todos los pagos —eso mezcla cuotas mensuales con prepagos anuales—, sino sumando primero por socio y promediando esas sumas. El orden importa: agregar en el nivel equivocado da un número que parece razonable y responde a otra pregunta. Antes de escribir una agregación, ten claro cuál es la unidad de la que hablas —socios, suscripciones, pagos, check-ins— y agrega en ese nivel.
### El JOIN y por qué a veces tiene que ser un LEFT
Cruzar tablas es el pan de cada día del analista, y hay un matiz sobre cómo se cruzan que decide más análisis de los que parece. El cruce normal, el JOIN a secas (o INNER JOIN), une dos tablas y se queda solo con las filas que casan en ambas: si cruzas socios con check-ins por INNER JOIN, obtienes los socios que tienen algún check-in, y los socios que nunca han venido desaparecen del resultado. La mayoría de las veces eso es lo que quieres. Pero cuando la pregunta es sobre quién NO hizo algo —quién no ha venido, quién no reservó—, el INNER JOIN te traiciona: se lleva justo a los que te interesan. Para esos casos existe el LEFT JOIN, que conserva todas las filas de la tabla de la izquierda aunque no tengan pareja en la derecha, rellenando con nulos donde no hay coincidencia. Cuál eliges no es un detalle técnico: cambia qué población estás midiendo.
En tu caso esto es crítico y lo vas a usar constantemente. Para contar la asistencia temprana de cada socio, necesitas un LEFT JOIN de socios con check-ins: si usaras INNER, los socios que se dieron de alta y no volvieron —cero check-ins, el tramo de asistencia baja— desaparecerían, y son precisamente los que peor renuevan, el corazón del hallazgo. Con LEFT JOIN esos socios aparecen con un recuento de cero, entran en el tramo bajo, y el análisis es honesto. La regla mental: si tu pregunta incluye a los que hicieron cero de algo, necesitas LEFT JOIN, porque el INNER los borra. Elegir mal el tipo de cruce es una de las formas más silenciosas de sesgar un análisis: el número sale, parece razonable, y está calculado sobre una población recortada sin que nadie lo note.
### Anatomía de una consulta de negocio: pensar por pasos con WITH
Las consultas de esta semana son más largas que un simple SELECT, y conviene entender su anatomía para no perderte. La pieza que las organiza es la cláusula WITH, que crea lo que se llama una tabla temporal con nombre, o CTE (por sus siglas en inglés). La idea es sencilla y cambia tu forma de escribir SQL: en lugar de meter toda la lógica en una consulta gigante e ilegible, la partes en pasos con nombre, cada uno resolviendo una parte del problema. En la consulta del LTV, por ejemplo, un primer paso (`ltv`) suma los pagos por socio, otro paso (`plan`) averigua el plan de cada socio, y la consulta final los junta y promedia. Cada paso es comprensible por sí mismo, y el resultado se lee como una receta: primero esto, luego esto, y al final júntalo. Un CTE bien puesto convierte una consulta que da miedo en una secuencia de pasos que cualquiera sigue.
Pensar por pasos con WITH no es solo cuestión de legibilidad: es cómo se ataca un problema complejo. Cuando te enfrentes a una pregunta de negocio enrevesada —«renovación por tramo de asistencia y por plan»—, la tentación del novato es intentar escribirla de una vez y frustrarse. El analista con oficio la descompone: «primero necesito el tramo de asistencia de cada socio (un paso), luego si renovó o no (otro paso), y al final los cruzo y agrupo (la consulta final)». Cada paso lo escribe y lo prueba por separado, y solo cuando cada uno funciona, los encadena. Esa forma de trabajar —descomponer un problema grande en pasos pequeños que se resuelven y comprueban uno a uno— no es solo de SQL: es la forma de resolver casi cualquier problema difícil. El CTE es la herramienta que la hace natural en SQL.
### SQL es declarativo: dices qué quieres, no cómo obtenerlo
Hay una diferencia profunda entre SQL y un lenguaje como Python que conviene entender, porque cambia cómo piensas cada consulta. En Python, cuando quieres sumar los pagos de un socio, tú escribes el cómo: recorre las filas, ve acumulando, agrupa. Le das a la máquina las instrucciones paso a paso. SQL es distinto: es declarativo, lo que significa que describes qué resultado quieres —«la suma de importes agrupada por socio, solo los pagos en estado ok»— y dejas que la base de datos decida cómo calcularlo de la forma más eficiente. No le dices cómo recorrer las filas ni en qué orden; le dices qué quieres ver, y ella se encarga. Esta diferencia es liberadora una vez la interiorizas: en SQL no programas un procedimiento, describes un resultado. Por eso una consulta bien escrita se lee casi como una frase en inglés: «selecciona el plan y la media del total, de esta tabla cruzada con esta otra, agrupado por plan».
Que SQL sea declarativo tiene una consecuencia práctica muy útil: la base de datos es libre de optimizar por dentro, y suele hacerlo mejor que tú. No tienes que preocuparte de si conviene recorrer primero una tabla u otra, de cómo ordenar las operaciones para que vaya rápido: el motor tiene un optimizador que reordena tu consulta para ejecutarla de la forma más eficiente que encuentra. Tú te concentras en describir bien el resultado; él se encarga del rendimiento. Esto no significa que puedas escribir cualquier cosa —una consulta mal planteada puede ser lenta o dar resultados equivocados—, pero sí que tu energía va a la lógica del negocio (qué quiero medir, cómo se define) y no a la mecánica de cómo recorrer datos. Para un analista, que piensa en preguntas de negocio, esa es exactamente la abstracción correcta: SQL te deja hablar el idioma de las preguntas, no el de las instrucciones.
Consejo de senior: cuando una consulta te salga tan larga que no la entiendas al releerla, párala y pártela en CTEs con nombres que digan qué hace cada paso (`vencidas`, `ltv`, `tramo`). Un buen nombre de CTE es documentación gratis: quien lee la consulta —incluido tu yo de dentro de un mes— entiende la lógica sin descifrar el SQL. Las consultas ilegibles no son señal de que seas más listo; son deuda que pagarás la próxima vez que tengas que tocarlas. La claridad en SQL, como en la prosa, es una cortesía con quien lee después, que muchas veces eres tú.
### Métricas de vanidad y métricas de verdad
No todas las métricas valen lo mismo, y una de las lecciones más caras que aprende un negocio es distinguir las que suben la moral de las que mueven la caja. Hay un nombre para las primeras: métricas de vanidad. Son números que siempre suben, que quedan bien en una diapositiva y que no ayudan a decidir nada: «total de altas históricas», «check-ins acumulados desde 2017», «socios que han pasado alguna vez por el gimnasio». Suben siempre —es imposible que bajen, porque son acumulados— y por eso no dicen nada sobre si el negocio va bien hoy. La caja del prepago anual es peligrosamente parecida a una métrica de vanidad: entra mucho dinero de golpe, el número luce, y esconde que ese socio quizá no vuelva. Un analista con criterio desconfía por instinto de cualquier número que solo pueda subir.
Las métricas de verdad, las que sirven para decidir, tienen una propiedad incómoda: pueden empeorar. La tasa de renovación puede bajar. El porcentaje de socios que vienen puede caer. Precisamente porque pueden ir a peor, te dicen algo real sobre el estado del negocio, y por eso son las que un director quiere en su panel. La diferencia entre una y otra no está en el dato en sí, sino en si sirve para actuar: «tenemos 9.000 activos» no te dice qué hacer; «la renovación del anual es del 41% frente al 60% del mensual» te dice exactamente dónde mirar. Cuando construyas cualquier cuadro de mando en tu carrera, la pregunta que separa el grano de la paja es: si este número empeora, ¿sabría el que lo mira qué hacer al respecto? Si la respuesta es no, probablemente es vanidad.
### El self-join por dentro: cruzar una tabla consigo misma
El self-join merece un párrafo propio porque es la técnica nueva de la semana y la que resuelve la renovación. La idea desconcierta la primera vez: ¿para qué cruzo la tabla de suscripciones consigo misma? La respuesta es que necesitas comparar unas filas con otras de la misma tabla. La pregunta «¿este socio, tras vencerle esta suscripción, arrancó otra?» compara una suscripción (la que vence) con las demás suscripciones del mismo socio (las candidatas a ser la renovación). Ambas viven en la misma tabla, así que para relacionarlas tienes que poner la tabla dos veces en la consulta, con dos nombres distintos —una la llamas `s` y otra `s2`—, y pedir que `s2` sea del mismo socio que `s`, distinta de ella, y que empiece justo cuando `s` acaba. Eso es cruzar una tabla consigo misma: dos copias con papeles distintos.
La forma que usas —EXISTS con una subconsulta— es una variante especialmente legible del self-join. EXISTS pregunta «¿hay al menos una fila que cumpla esto?» y devuelve verdadero o falso, sin traer los datos, solo confirmando si existe. Es la traducción más literal de «¿existe otra suscripción suya que empiece cuando esta acaba?». Por dentro, la base de datos recorre cada suscripción vencida y, para cada una, busca entre las suscripciones del mismo socio; a eso se le llama una subconsulta correlacionada, porque la subconsulta depende de la fila de fuera (usa su `socio_id` y su `fecha_fin`). Es potente y es legible, aunque en tablas enormes puede ser lenta, porque repite la búsqueda por cada fila. Para las 11.000 suscripciones de VueltaFit va sobrada; en tablas de millones, un analista consideraría alternativas como las funciones de ventana, pero eso es otra historia.
### Agregar es resumir, y resumir siempre pierde algo
Cada vez que calculas un promedio, un total o una tasa global, estás resumiendo muchas filas en un número, y todo resumen pierde información por definición. La renovación global del 52% resume a miles de socios anuales y mensuales, jóvenes y mayores, fanáticos y ausentes, en una sola cifra. Esa compresión es útil —no puedes decidir mirando miles de filas— pero es también donde se esconden las historias. El arte del analista no es solo calcular el resumen, sino saber cuándo el resumen engaña y hay que abrirlo. La regla práctica: todo promedio global merece la pregunta «¿y si lo parto?». Partir por plan, por sede, por comportamiento. La mayoría de las veces la partición confirma que el total era representativo; de vez en cuando, revela que el total escondía dos mundos opuestos. Y esas veces son las que cambian una decisión.
Hay un fenómeno con nombre que conviene tener presente: a veces una tendencia que se ve en el total desaparece o se invierte cuando desagregas por un tercer factor. Suena raro, pero pasa, y es la razón por la que un analista prudente nunca se fía del agregado sin más. Esta misma semana lo vas a vivir en su forma más pura: la renovación global (52%) parece sana, pero al partir por plan aparece la grieta, y al partir además por comportamiento (la asistencia temprana) se descubre que ni siquiera es el plan lo que manda. Cada corte revela una capa que el anterior escondía. Por eso hoy calculas los totales —hay que tenerlos, son el punto de partida—, pero sabes que la historia de verdad empieza mañana, cuando empieces a cortar.
Consejo de senior: cuando un socio tiene varias suscripciones encadenadas, cuéntalo una sola vez por su plan para el reparto y el LTV, o inflarás los números. La forma limpia es quedarte con su primera suscripción (con ROW_NUMBER particionando por socio y ordenando por fecha de inicio, y filtrando la número 1). Contar cada suscripción como si fuera un socio distinto es un error clásico que hace que «el 40% son anuales» se convierta en un número que no cuadra con nadie. Piensa siempre en la unidad de la que hablas: ¿socios o suscripciones? No son lo mismo.
Consejo de senior: el LTV medio se calcula sumando primero por socio y promediando después, no promediando todos los pagos de golpe. Si promedias pagos, un prepago anual de 449 € pesa lo mismo que una cuota mensual de 39 €, y mezclas peras con manzanas. Sumar por socio primero te da el valor de cada persona, y promediar eso te da el valor de una persona media. El orden de las operaciones en una media agregada cambia el resultado: agrupa por la entidad de la que quieres hablar antes de promediar.
Regístrate para guardar tu progreso.