En este escenario partimos de un listado de clientes:
...y de una tabla de compras de cada uno de ellos:
El objetivo es obtener un listado de clientes en el que se muestre el número de días (por ejemplo, podría ser otro período) entre compras. Para hacer el escenario sencillo los clientes reciben como nombre "Cliente x", siendo x el número de compras realizadas (de esta forma, el Cliente 0 no ha realizado ninguna, el Cliente 1 ha realizado una, etc.), y la frecuencia de compra en días para cada cliente coincide también con x. Así, el cliente 2 realizó una primera compra el 3 de enero, y una segunda dos días más tarde, el 5 de enero.
Una vez hemos asegurado que el modelo de datos incluye las relaciones adecuadas (incluyendo una relación entre la tabla de ventas y el necesario calendario), podemos crear una tabla calculada que, usando la función SELECTCOLUMNS, extraiga el listado de clientes y agregue la información necesaria. Partimos, por lo tanto, de la siguiente expresión DAX que define esta primera versión de nuestra tabla de resultados:
Frecuencia de compra =
SELECTCOLUMNS(
Clientes;
"Nombre"; Clientes[Nombre]
)
Aunque podríamos calcular directamente la frecuencia de compra para cada uno de ellos, hagámoslo paso por paso, incluyendo una columna adicional para cada uno de los datos que necesitamos.
Si entendemos por frecuencia de compra el número de días transcurridos entre la primera compra y la última dividido entre el número de compras realizadas, en primer lugar sería preciso calcular las fechas de primera y de última compra por cliente, para lo que vamos a recurrir a las funciones FIRSTDATE y LASTDATE:
Frecuencia de compra =
SELECTCOLUMNS(
Clientes;
"Nombre"; Clientes[Nombre];
"Primera compra"; FIRSTDATE(Calendario[Fecha]);
"Última compra"; LASTDATE(Calendario[Fecha])
)
El cálculo del rango de días entre ambas fechas se reduce a una sencilla resta, que realizaremos usando la función DATEDIFF, función que nos permite especificar el período a considerar -días, en nuestro ejemplo-:
Frecuencia de compra =
SELECTCOLUMNS(
Clientes;
"Nombre"; Clientes[Nombre];
"Primera compra"; FIRSTDATE(Calendario[Fecha]);
"Última compra"; LASTDATE(Calendario[Fecha]);
"Rango"; DATEDIFF(FIRSTDATE(Calendario[Fecha]); LASTDATE(Calendario[Fecha]); DAY)
)
Debemos entender que estamos realizando un enfoque un tanto ingenuo del problema al presuponer que el cliente existe como tal desde su primera compra y solo hasta la última. Más realista sería considerar como comienzo del período el día en el que el cliente "se dio de alta como tal", hubiese realizado o no una compra, y/o considerar como fin del período el día actual, por ejemplo.
Considérese también que, al crearse la tabla calculada en un entorno de contexto de fila, para cada cliente se extrae la información de la tabla remota relacionada con él. Así, cuando se está calculando la primera fecha de compra para el cliente X, la expresión
FIRSTDATE(Calendario[Fecha])
...filtra el campo Fecha de la tabla Calendario de forma que solo incluya las fechas para las que existen compras asociadas al cliente que corresponda.
El siguiente paso es contar el número de compras por cliente, para lo que podemos extraer la tabla Ventas (una vez filtrada por el contexto, para lo que usaremos la función RELATEDTABLE) y contar el número de filas que tiene con COUNTROWS:
Frecuencia de compra =
SELECTCOLUMNS(
Clientes;
"Nombre"; Clientes[Nombre];
"Primera compra"; FIRSTDATE(Calendario[Fecha]);
"Última compra"; LASTDATE(Calendario[Fecha]);
"Rango"; DATEDIFF(FIRSTDATE(Calendario[Fecha]); LASTDATE(Calendario[Fecha]); DAY);
"Nº de compras"; COUNTROWS(RELATEDTABLE(Ventas))
)
Por último queda lo más sencillo, que es dividir el rango de fechas entre el número de compras, para lo que recurriremos a la función DIVIDE:
Frecuencia de compra =
SELECTCOLUMNS(
Clientes;
"Nombre"; Clientes[Nombre];
"Primera compra"; FIRSTDATE(Calendario[Fecha]);
"Última compra"; LASTDATE(Calendario[Fecha]);
"Rango"; DATEDIFF(FIRSTDATE(Calendario[Fecha]); LASTDATE(Calendario[Fecha]); DAY);
"Nº de compras"; COUNTROWS(RELATEDTABLE(Ventas));
"Frecuencia de compra"; DIVIDE(
DATEDIFF(FIRSTDATE(Calendario[Fecha]); LASTDATE(Calendario[Fecha]); DAY);
COUNTROWS(RELATEDTABLE(Ventas))
)
)
Comprobamos que, en esta primera versión de la expresión, si un cliente no ha realizado ninguna compra se muestra un BLANK, y si ha realizado una única compra de devuelve una frecuencia de 1. Podríamos completar nuestro DIVIDE con alguna función lógica que realizase un cálculo u otro en función del número de compras y, de esta forma, gestionar estas excepciones.
Puede descargarse el fichero Excel y el informe Power BI resultante aquí.