LASTDATE https://interactivechaos.ovh/es es Cálculo de totales acumulados https://interactivechaos.ovh/es/dax/scenario/calculo-de-totales-acumulados <span class="field field--name-title field--type-string field--label-hidden">Cálculo de totales acumulados</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/es/user/1" typeof="schema:Person" property="schema:name" datatype="">admin</span></span> <span class="field field--name-created field--type-created field--label-hidden">Lun, 03/12/2018 - 20:19</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Un escenario frecuente es aquel en el que queremos calcular el total acumulado, incluyendo todos los datos hasta una cierta fecha y no solo los implicados en el contexto de filtro actual. Por ejemplo, si suponemos la existencia de una tabla de ventas <span class="code">Sales</span> que contiene una columna <span class="code">Amount</span> con la cifra de ventas, podríamos definir una medida que calculase la suma de esta columna con la siguiente expresión DAX:</p> <div class="codigo">Sales = SUM(Sales[Amount])</div> <p>Lógicamente, esta medida se va a adaptar al contexto de filtro, por lo que si la llevamos a una matriz en la que se esté desagregando las ventas por año:</p> <a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_01.png"><img alt="Sales by year" class="image-colorbox__max_800_px align-center" data-entity-type="file" data-entity-uuid="insert-max_800_px-48c7d6c1-4870-4d74-b165-caba177a4d17" data-insert-attach="{&quot;id&quot;: &quot;48c7d6c1-4870-4d74-b165-caba177a4d17&quot;, &quot;attributes&quot;: {&quot;alt&quot;: [&quot;alt&quot;, &quot;description&quot;], &quot;title&quot;: [&quot;title&quot;]}}" data-insert-class="" data-insert-type="image" src="/sites/default/files/styles/max_800_px/public/2023-01/dax_scenario_calculo_totales_01.png" /></a> <p>...vemos que, para cada año, la cifra de ventas mostrada incluye solo las ventas de dicho año.</p> <p>Lo que querríamos sería que, en cada evaluación de la medida, el período temporal considerado comenzase el primer día para que el hubo ventas (supongamos que el 1 de enero de 2015) y se extendiese hasta la última fecha del "período actual". Por ejemplo, en la cifra correspondiente al año 2018 el período actual es el correspondiente a los 365 días de dicho año. Pues bien, para el cálculo del acumulado para dicho año querríamos que se considerase el período comprendido entre el 1 de enero de 2015 y el 31 de diciembre de 2018. Es decir, escrito en pseudo-código:</p> <div class="codigo">Accumulated sales = <br /> CALCULATE(<br />     [Sales],<br />     Período entre la primera fecha disponible y la última fecha del contexto actual<br /> )</div> <p>El período en cuestión puede calcularse usando la función <a href="/es/dax/function/datesbetween">DATESBETWEEN</a> que devuelve el conjunto de fechas entre dos dadas. Si el calendario está contenido en la tabla <span class="code">Calendar</span>, tendríamos, por lo tanto, que codificar la siguiente medida:</p> <div class="codigo"> <p>Accumulated sales = <br /> CALCULATE(<br />     [Sales],<br />     DATESBETWEEN(<br />         'Calendar'[Date],<br />         Primera fecha disponible,<br />         Última fecha del contexto actual<br />     )<br /> )</p> </div> <p>Ahora bien, es el cálculo de esas dos fechas lo que resulta más complejo, pues queremos que la primera fecha ("<em>Primera fecha disponible</em>") sea absoluta y haga referencia a la primera fecha disponible en el calendario, mientras que la segunda ("<em>Última fecha del contexto actual</em>") queremos que se adapte al contexto.</p> <p>Para la obtención de la primera fecha disponible en el calendario deberemos asegurarnos de que no se están aplicando filtros al mismo, para lo que podemos usar la función <a href="/es/dax/function/all">ALL</a> (lo que va a devolver una tabla). Y para la extracción de la primera fecha disponible de dicha tabla no podemos usar la función <a href="/es/dax/function/min">MIN</a> pues ésta exige una columna como argumento, de forma que tendremos que usar la función <a href="/es/dax/function/firstdate">FIRSTDATE</a>, que sí acepta una tabla como argumento y devuelve otra tabla (con la fecha más antigua disponible), tabla que podemos pasar a la función <a href="/es/dax/function/calculate">CALCULATE</a> como argumento de filtro:</p> <div class="codigo">FIRSTDATE(ALL(Sales[Order Date]))</div> <p>Para el cálculo de la última fecha del contexto actual no tenemos más que utilizar la función <a href="/es/dax/function/max">MAX</a> pasando como argumento la columna temporal que está desagregando nuestro objeto visual: la columna <span class="code">'Calendar'[Date]</span>. Es decir, la última fecha del contexto actual vendría dada por:</p> <div class="codigo">MAX('Calendar'[Date])</div> <p>Es decir, la expresión</p> <div class="codigo">DATESBETWEEN(<br />     'Calendar'[Date],<br />     FIRSTDATE(ALL(Sales[Order Date])),<br />     MAX('Calendar'[Date])<br /> )</div> <p>...va a devolver el conjunto de fechas del calendario entre la más antigua disponible y la última implicada en el contexto actual. Podemos escribir, por lo tanto, la medida que devuelve las ventas acumuladas:</p> <div class="codigo">Accumulated sales =<br /> CALCULATE(<br />     [Sales],<br />     DATESBETWEEN(<br />         'Calendar'[Date],<br />         FIRSTDATE(ALL(Sales[Order Date])),<br />         MAX('Calendar'[Date])<br />     )<br /> )</div> <p>Si quisiéramos utilizar variables para hacer más legible el código, podríamos crear dos variables, <span class="code">__firstdate</span> y <span class="code">__lastDate</span> conteniendo las dos fechas implicadas en el código anterior:</p> <div class="codigo">Accumulated sales =<br /> VAR __firstDate = FIRSTDATE(ALL(Sales[Order Date]))<br /> VAR __lastDate = MAX('Calendar'[Date])<br /> RETURN<br />     CALCULATE(<br />         [Sales],<br />         DATESBETWEEN(<br />             'Calendar'[Date],<br />             __firstDate,<br />             __lastDate<br />         )<br />     )</div> <p>Ahora, si llevamos la medida anterior a nuestra matriz, comprobamos que se están acumulando las ventas tal y como queríamos:</p> <a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_02.png"><img alt="Accumulated sales by year" class="image-colorbox__max_800_px align-center" data-entity-type="file" data-entity-uuid="insert-max_800_px-dab86cbb-c629-45d8-9afa-ee730c81aa40" data-insert-attach="{&quot;id&quot;: &quot;dab86cbb-c629-45d8-9afa-ee730c81aa40&quot;, &quot;attributes&quot;: {&quot;alt&quot;: [&quot;alt&quot;, &quot;description&quot;], &quot;title&quot;: [&quot;title&quot;]}}" data-insert-class="" data-insert-type="image" src="/sites/default/files/styles/max_800_px/public/2023-01/dax_scenario_calculo_totales_02.png" /></a> <p>Y, por supuesto, si mostramos la matriz desagregada por cualquier otro nivel de nuestra jerarquía temporal, por trimestres, por ejemplo, el cálculo de las ventas acumuladas sigue realizándose correctamente:</p> <a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2023-01/dax_scenario_calculo_totales_03.png"><img alt="Accumulated sales by quarter" class="image-colorbox__max_800_px align-center" data-entity-type="file" data-entity-uuid="insert-max_800_px-e40ca511-b94c-46b4-bc19-759574e3d53f" data-insert-attach="{&quot;id&quot;: &quot;e40ca511-b94c-46b4-bc19-759574e3d53f&quot;, &quot;attributes&quot;: {&quot;alt&quot;: [&quot;alt&quot;, &quot;description&quot;], &quot;title&quot;: [&quot;title&quot;]}}" data-insert-class="" data-insert-type="image" src="/sites/default/files/styles/max_800_px/public/2023-01/dax_scenario_calculo_totales_03.png" /></a></div> <div class="field field--name-field-funciones-dax-involucradas field--type-entity-reference field--label-above"> <div class="field__label">Funciones DAX involucradas</div> <div class="field__items"> <div class="field__item"><a href="/es/taxonomy/term/28" hreflang="es">SUM</a></div> <div class="field__item"><a href="/es/taxonomy/term/33" hreflang="es">CALCULATE</a></div> <div class="field__item"><a href="/es/taxonomy/term/38" hreflang="es">DATESBETWEEN</a></div> <div class="field__item"><a href="/es/taxonomy/term/37" hreflang="es">ALL</a></div> <div class="field__item"><a href="/es/taxonomy/term/77" hreflang="es">MIN</a></div> <div class="field__item"><a href="/es/taxonomy/term/59" hreflang="es">MAX</a></div> <div class="field__item"><a href="/es/taxonomy/term/35" hreflang="es">LASTDATE</a></div> <div class="field__item"><a href="/es/taxonomy/term/68" hreflang="es">VAR</a></div> </div> </div> <div class="field field--name-field-dax-esc-dificultad field--type-list-string field--label-above"> <div class="field__label">Dificultad</div> <div class="field__item">Intermedia</div> </div> Mon, 03 Dec 2018 19:19:03 +0000 admin 16 at https://interactivechaos.ovh Cálculo de una métrica a principio de cada mes https://interactivechaos.ovh/es/dax/scenario/calculo-de-una-metrica-principio-de-cada-mes <span class="field field--name-title field--type-string field--label-hidden">Cálculo de una métrica a principio de cada mes</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/es/user/1" typeof="schema:Person" property="schema:name" datatype="">admin</span></span> <span class="field field--name-created field--type-created field--label-hidden">Vie, 31/07/2020 - 08:10</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>En este escenario partimos de una tabla en la que se incluye información de los cambios de una cierta métrica por día. Por ejemplo, supongamos que se trata de las variaciones en la cantidad de cierto producto que hay en nuestro almacén. En este ejemplo la tabla se llama <em>data</em> y los dos campos que contiene son <em>Fecha</em> y <em>Movimientos</em>:</p> <a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2020-07/dax-0090.jpg"><img alt="Tabla de datos" class="image-colorbox__max_800_px align-center" data-entity-type="file" data-entity-uuid="insert-max_800_px-04f04b66-88c9-446b-90e2-327c78cd4142" data-insert-attach="{&quot;id&quot;: &quot;04f04b66-88c9-446b-90e2-327c78cd4142&quot;, &quot;attributes&quot;: {&quot;alt&quot;: [&quot;alt&quot;, &quot;description&quot;], &quot;title&quot;: [&quot;title&quot;]}}" data-insert-class="" data-insert-type="image" src="/sites/default/files/styles/max_800_px/public/2020-07/dax-0090.jpg" /></a> <p>Obsérvese que la tabla incluye el último día del año 2019 aun cuando en este escenario queremos trabajar únicamente con el año 2020. Explicaré más adelante el motivo de comenzar la tabla por esta fecha.</p> <p>El objetivo es calcular el estado de nuestro almacén a comienzo de cada mes (o de cada trimestre, o de cada año).</p> <p>Para esto, tras leer los datos desde Power BI vamos a calcular una medida base que simplemente sume el campo <em>Movimientos</em> (para el contexto en el que nos encontremos en cada momento):</p> <div class="codigo"> <p>Quantity = SUM(data[Movimientos])</p> </div> <p>Hacemos esto para evitar tener que sumar dicho campo cada vez que necesitemos realizar este cálculo en futuras medidas.</p> <p>Ahora podemos calcular el total acumulado de nuestros movimientos. Para esto vamos a crear una medida que sume <em>Quantity</em> desde el comienzo de los tiempos hasta "la fecha actual" (hasta la fecha máxima de cada contexto de cálculo). Todas las <a href="https://www.interactivechaos.com/recursos-educativos/funciones-dax?title=&amp;field_funcion_dax_categoria_value%5B%5D=Funciones+de+inteligencia+de+tiempo">funciones DAX de inteligencia de tiempo</a> requieren un calendario que sirva de referencia. Si tenemos una tabla con este calendario, estupendo. Si no, podemos crear una tabla calculada con la función <a href="https://www.interactivechaos.com/dax/function/calendarauto">CALENDARAUTO</a>. Supongamos que llamamos a esta nueva tabla <em>Calendar</em>:</p> <div class="codigo"> <p>Calendar = CALENDARAUTO()</p> </div> <a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2020-07/dax-0091.jpg"><img alt="Función DAX CALENDARAUTO" class="image-colorbox__max_800_px align-center" data-entity-type="file" data-entity-uuid="insert-max_800_px-45f4f9d9-a89a-44c9-999a-e86f49967944" data-insert-attach="{&quot;id&quot;: &quot;45f4f9d9-a89a-44c9-999a-e86f49967944&quot;, &quot;attributes&quot;: {&quot;alt&quot;: [&quot;alt&quot;, &quot;description&quot;], &quot;title&quot;: [&quot;title&quot;]}}" data-insert-class="" data-insert-type="image" src="/sites/default/files/styles/max_800_px/public/2020-07/dax-0091.jpg" /></a> <p>Una vez creada esta tabla no debemos olvidar crear una relación entre el recién creado campo <em>Calendar[Date]</em> y el campo <em>Data[Fecha]</em>.</p> <p>La medida que calcula el acumulado de nuestra medida <em>Quantity</em> (acumulado "hasta la fecha actual") es la siguiente:</p> <div class="codigo"> <p>Accumulated Quantity = <br />     CALCULATE(<br />         [Quantity],<br />         DATESBETWEEN(<br />             'Calendar'[Date],<br />             FIRSTDATE(ALL('Calendar'[Date])),<br />             LASTDATE('Calendar'[Date])<br />         )<br />     )</p> </div> <p>Básicamente estamos recalculando la medida <em>Quantity</em> (para lo que usamos la función <a href="https://www.interactivechaos.com/dax/function/calculate">CALCULATE</a>) en un nuevo contexto: aquel formado por todas las fechas entre la primera que encontremos en el calendario (usando la función <a href="https://www.interactivechaos.com/dax/function/firstdate">FIRSTDATE</a>) y la última fecha "del contexto actual" (usando la función <a href="https://www.interactivechaos.com/dax/function/lastdate">LASTDATE</a>). Obsérvese el uso de la función <a href="https://www.interactivechaos.com/dax/function/all">ALL</a> como argumento de FIRSTDATE: es lo que nos permite asegurar que estamos extrayendo el primer día de todo el calendario, y no el primer día del contexto actual.</p> <p>Podemos crear una tabla en el lienzo de Power BI para ver el resultado hasta ahora:</p> <a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2020-07/dax-0092.jpg"><img alt="Tabla con los movimientos y el acumulado" class="image-colorbox__max_800_px align-center" data-entity-type="file" data-entity-uuid="insert-max_800_px-f88cb230-f0de-458d-9388-ef753ced4737" data-insert-attach="{&quot;id&quot;: &quot;f88cb230-f0de-458d-9388-ef753ced4737&quot;, &quot;attributes&quot;: {&quot;alt&quot;: [&quot;alt&quot;, &quot;description&quot;], &quot;title&quot;: [&quot;title&quot;]}}" data-insert-class="" data-insert-type="image" src="/sites/default/files/styles/max_800_px/public/2020-07/dax-0092.jpg" /></a> <p>A la tabla anterior se ha llevado el campo <em>Calendar[Date]</em> y las medidas <em>Quantity</em> y <em>Accumulated Quantity</em>, y, tal y como se muestra en la imagen, se ha filtrado de forma que solo muestre fechas a partir del 1 de enero de 2020.</p> <p>Por último, no tenemos más que calcular, para cada fecha, el valor de la medida con el acumulado <em>el primer día del mes correspondiente</em>. Para esto podemos usar la función <a href="https://www.interactivechaos.com/dax/function/openingbalancemonth">OPENINGBALANCEMONTH</a> (o las funciones equivalentes <a href="https://www.interactivechaos.com/dax/function/openingbalancequarter">OPENINGBALANCEQUARTER</a> y <a href="https://www.interactivechaos.com/dax/function/openingbalanceyear">OPENINGBALANCEYEAR</a> si quisiéramos calcular dicho acumulado el primer día de cada trimestre o de cada año):</p> <div class="codigo"> <p>Quantity First Day of Month = <br />     OPENINGBALANCEMONTH(<br />         [Accumulated Quantity],<br />         'Calendar'[Date]<br />     )</p> </div> <p>Con esta medida estamos asociando a cada fecha (a cada contexto temporal, en realidad, sea de un día o no) la cifra de <em>Accumulated Quantity</em> del primer día del mes al que pertenece dicha fecha. Si llevamos esta medida a nuestra tabla obtenemos el siguiente resultado:</p> <a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2020-07/dax-0093.jpg"><img alt="Acumulado el primer día de cada mes" class="image-colorbox__max_800_px align-center" data-entity-type="file" data-entity-uuid="insert-max_800_px-23c459c9-da03-4a99-8587-a1b4104ad45b" data-insert-attach="{&quot;id&quot;: &quot;23c459c9-da03-4a99-8587-a1b4104ad45b&quot;, &quot;attributes&quot;: {&quot;alt&quot;: [&quot;alt&quot;, &quot;description&quot;], &quot;title&quot;: [&quot;title&quot;]}}" data-insert-class="" data-insert-type="image" src="/sites/default/files/styles/max_800_px/public/2020-07/dax-0093.jpg" /></a> <p>En la imagen anterior (que solo muestra la tabla entre el 1 de enero y el 5 de febrero) vemos que a cualquier día del mes de enero se asocia el valor 0 (acumulado a principio de dicho mes) y que a cualquier día de febrero se asocia el valor 21 (acumulado a principio de dicho mes). Y éste es el motivo de haber comenzado nuestra tabla de movimientos por el día 31 de diciembre de 2019: la función OPENINGBALANCEMONTH devuelve, en realidad, el valor de la métrica de que se trate <em>antes del primer día del mes correspondiente</em> -lo que tiene mucha lógica-: si el primer día de mi tabla (supongamos que es el 1 de enero) tengo un incremento de +2 (por ejemplo), la cifra acumulada a principio de dicho mes era de 0 (la cifra correspondiente al final del 31 de diciembre). De igual forma, si a finales de enero el total acumulado era de 21, con independencia del incremento que se produzca el 1 de febrero, el total acumulado <em>a principios de febrero</em> era de 21 (es decir, la cifra del último día de enero).</p> <p>Si no hubiésemos incluido la fecha del 31 de diciembre, todos los días de enero habrían recibido como total acumulado a principio de mes el valor 127, que es la suma total de la columna <em>Quantity</em>, sencillamente porque no habría un <em>día del mes anterior</em> para hacer el cálculo y DAX, por diseño, consideraría toda la tabla.</p> </div> <div class="field field--name-field-funciones-dax-involucradas field--type-entity-reference field--label-above"> <div class="field__label">Funciones DAX involucradas</div> <div class="field__items"> <div class="field__item"><a href="/es/taxonomy/term/28" hreflang="es">SUM</a></div> <div class="field__item"><a href="/es/taxonomy/term/90" hreflang="es">CALENDARAUTO</a></div> <div class="field__item"><a href="/es/taxonomy/term/33" hreflang="es">CALCULATE</a></div> <div class="field__item"><a href="/es/taxonomy/term/38" hreflang="es">DATESBETWEEN</a></div> <div class="field__item"><a href="/es/taxonomy/term/36" hreflang="es">FIRSTDATE</a></div> <div class="field__item"><a href="/es/taxonomy/term/35" hreflang="es">LASTDATE</a></div> <div class="field__item"><a href="/es/taxonomy/term/37" hreflang="es">ALL</a></div> <div class="field__item"><a href="/es/taxonomy/term/128" hreflang="es">OPENINGBALANCEMONTH</a></div> </div> </div> Fri, 31 Jul 2020 06:10:13 +0000 admin 2371 at https://interactivechaos.ovh Cálculo de la frecuencia de compra de los clientes https://interactivechaos.ovh/es/dax/scenario/calculo-de-la-frecuencia-de-compra-de-los-clientes <span class="field field--name-title field--type-string field--label-hidden">Cálculo de la frecuencia de compra de los clientes</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/es/user/1" typeof="schema:Person" property="schema:name" datatype="">admin</span></span> <span class="field field--name-created field--type-created field--label-hidden">Lun, 14/10/2019 - 12:50</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>En este escenario partimos de un listado de clientes:</p> <a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2019-10/dax-0024.jpg"><img alt="Tabla de clientes" class="image-colorbox__max_800_px align-center" data-entity-type="file" data-entity-uuid="insert-max_800_px-350e337f-140f-4fa2-bda4-0f03477cb3c2" data-insert-attach="{&quot;id&quot;: &quot;350e337f-140f-4fa2-bda4-0f03477cb3c2&quot;, &quot;attributes&quot;: {&quot;alt&quot;: [&quot;alt&quot;, &quot;description&quot;], &quot;title&quot;: [&quot;title&quot;]}}" data-insert-class="" data-insert-type="image" src="/sites/default/files/styles/max_800_px/public/2019-10/dax-0024.jpg" /></a> <p>...y de una tabla de compras de cada uno de ellos:</p> <a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2019-10/dax-0025.jpg"><img alt="Tabla de ventas" class="image-colorbox__max_800_px align-center" data-entity-type="file" data-entity-uuid="insert-max_800_px-03329b88-76e4-4c9b-8765-af78475b80e1" data-insert-attach="{&quot;id&quot;: &quot;03329b88-76e4-4c9b-8765-af78475b80e1&quot;, &quot;attributes&quot;: {&quot;alt&quot;: [&quot;alt&quot;, &quot;description&quot;], &quot;title&quot;: [&quot;title&quot;]}}" data-insert-class="" data-insert-type="image" src="/sites/default/files/styles/max_800_px/public/2019-10/dax-0025.jpg" /></a> <p>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 <em>Cliente 0</em> no ha realizado ninguna, el <em>Cliente 1</em> 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.</p> <p>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 <a href="/dax/function/selectcolumns">SELECTCOLUMNS</a>, 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:</p> <div class="codigo"> <p>Frecuencia de compra = <br />     SELECTCOLUMNS(<br />         Clientes;<br />         "Nombre"; Clientes[Nombre]<br />     )</p> </div> <a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2019-10/dax-0026.jpg"><img alt="Listado de clientes" class="image-colorbox__max_800_px align-center" data-entity-type="file" data-entity-uuid="insert-max_800_px-e53eaa7f-c9ca-4db7-8f55-7fbf3b792f47" data-insert-attach="{&quot;id&quot;: &quot;e53eaa7f-c9ca-4db7-8f55-7fbf3b792f47&quot;, &quot;attributes&quot;: {&quot;alt&quot;: [&quot;alt&quot;, &quot;description&quot;], &quot;title&quot;: [&quot;title&quot;]}}" data-insert-class="" data-insert-type="image" src="/sites/default/files/styles/max_800_px/public/2019-10/dax-0026.jpg" /></a> <p>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.</p> <p>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 <a href="/dax/function/firstdate">FIRSTDATE</a> y <a href="/dax/function/lastdate">LASTDATE</a>:</p> <div class="codigo"> <p>Frecuencia de compra = <br />     SELECTCOLUMNS(<br />         Clientes;<br />         "Nombre"; Clientes[Nombre];<br />         "Primera compra"; FIRSTDATE(Calendario[Fecha]);<br />         "Última compra"; LASTDATE(Calendario[Fecha])<br />     )</p> </div> <a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2019-10/dax-0027.jpg"><img alt="Listado de clientes con primera y última fecha de compra" class="image-colorbox__max_800_px align-center" data-entity-type="file" data-entity-uuid="insert-max_800_px-5c3969df-7095-40d4-b46e-af97df4d2797" data-insert-attach="{&quot;id&quot;: &quot;5c3969df-7095-40d4-b46e-af97df4d2797&quot;, &quot;attributes&quot;: {&quot;alt&quot;: [&quot;alt&quot;, &quot;description&quot;], &quot;title&quot;: [&quot;title&quot;]}}" data-insert-class="" data-insert-type="image" src="/sites/default/files/styles/max_800_px/public/2019-10/dax-0027.jpg" /></a> <p>El cálculo del rango de días entre ambas fechas se reduce a una sencilla resta, que realizaremos usando la función <a href="/dax/function/datediff">DATEDIFF</a>, función que nos permite especificar el período a considerar -días, en nuestro ejemplo-:</p> <div class="codigo"> <p>Frecuencia de compra = <br />     SELECTCOLUMNS(<br />         Clientes;<br />         "Nombre"; Clientes[Nombre];<br />         "Primera compra"; FIRSTDATE(Calendario[Fecha]);<br />         "Última compra"; LASTDATE(Calendario[Fecha]);<br />         "Rango"; DATEDIFF(FIRSTDATE(Calendario[Fecha]); LASTDATE(Calendario[Fecha]); DAY)<br />     )</p> </div> <a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2019-10/dax-0028.jpg"><img alt="Listado de clientes con el rango de días de compras" class="image-colorbox__max_800_px align-center" data-entity-type="file" data-entity-uuid="insert-max_800_px-0c5b04ec-58bd-46b2-a673-efde628eabbb" data-insert-attach="{&quot;id&quot;: &quot;0c5b04ec-58bd-46b2-a673-efde628eabbb&quot;, &quot;attributes&quot;: {&quot;alt&quot;: [&quot;alt&quot;, &quot;description&quot;], &quot;title&quot;: [&quot;title&quot;]}}" data-insert-class="" data-insert-type="image" src="/sites/default/files/styles/max_800_px/public/2019-10/dax-0028.jpg" /></a> <p>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.</p> <p>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</p> <div class="codigo"> <p>FIRSTDATE(Calendario[Fecha])</p> </div> <p>...filtra el campo <em>Fecha</em> de la tabla <em>Calendario</em> de forma que solo incluya las fechas para las que existen compras asociadas al cliente que corresponda.</p> <p>El siguiente paso es contar el número de compras por cliente, para lo que podemos extraer la tabla <em>Ventas</em> (una vez filtrada por el contexto, para lo que usaremos la función <a href="/dax/function/relatedtable">RELATEDTABLE</a>) y contar el número de filas que tiene con <a href="/dax/function/countrows">COUNTROWS</a>:</p> <div class="codigo"> <p>Frecuencia de compra = <br />     SELECTCOLUMNS(<br />         Clientes;<br />         "Nombre"; Clientes[Nombre];<br />         "Primera compra"; FIRSTDATE(Calendario[Fecha]);<br />         "Última compra"; LASTDATE(Calendario[Fecha]);<br />         "Rango"; DATEDIFF(FIRSTDATE(Calendario[Fecha]); LASTDATE(Calendario[Fecha]); DAY);<br />         "Nº de compras"; COUNTROWS(RELATEDTABLE(Ventas))<br />     )</p> </div> <a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2019-10/dax-0029.jpg"><img alt="Listado de clientes con el rango de compras y número de éstas" class="image-colorbox__max_800_px align-center" data-entity-type="file" data-entity-uuid="insert-max_800_px-b68efa25-a5d8-4ce5-8aa3-96568aef9119" data-insert-attach="{&quot;id&quot;: &quot;b68efa25-a5d8-4ce5-8aa3-96568aef9119&quot;, &quot;attributes&quot;: {&quot;alt&quot;: [&quot;alt&quot;, &quot;description&quot;], &quot;title&quot;: [&quot;title&quot;]}}" data-insert-class="" data-insert-type="image" src="/sites/default/files/styles/max_800_px/public/2019-10/dax-0029.jpg" /></a> <p>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 <a href="/dax/function/divide">DIVIDE</a>:</p> <div class="codigo"> <p>Frecuencia de compra = <br />     SELECTCOLUMNS(<br />         Clientes;<br />         "Nombre"; Clientes[Nombre];<br />         "Primera compra"; FIRSTDATE(Calendario[Fecha]);<br />         "Última compra"; LASTDATE(Calendario[Fecha]);<br />         "Rango"; DATEDIFF(FIRSTDATE(Calendario[Fecha]); LASTDATE(Calendario[Fecha]); DAY);<br />         "Nº de compras"; COUNTROWS(RELATEDTABLE(Ventas));<br />         "Frecuencia de compra"; DIVIDE(<br />             DATEDIFF(FIRSTDATE(Calendario[Fecha]); LASTDATE(Calendario[Fecha]); DAY);<br />             COUNTROWS(RELATEDTABLE(Ventas))<br />         )<br />     )</p> </div> <a class="colorbox insert-colorbox" data-colorbox-gallery="gallery-node" data-insert-class="" data-insert-type="image" href="/sites/default/files/2019-10/dax-0030.jpg"><img alt="Listado de clientes con su frecuencia de compras" class="image-colorbox__max_800_px align-center" data-entity-type="file" data-entity-uuid="insert-max_800_px-a1dd98da-72fb-45f2-a860-f2a054bc67d1" data-insert-attach="{&quot;id&quot;: &quot;a1dd98da-72fb-45f2-a860-f2a054bc67d1&quot;, &quot;attributes&quot;: {&quot;alt&quot;: [&quot;alt&quot;, &quot;description&quot;], &quot;title&quot;: [&quot;title&quot;]}}" data-insert-class="" data-insert-type="image" src="/sites/default/files/styles/max_800_px/public/2019-10/dax-0030.jpg" /></a> <p>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.</p> <p>Puede descargarse el fichero Excel y el informe Power BI resultante <a href="https://www.interactivechaos.com/sites/default/files/data/calculo_de_la_frecuencia_de_compra_de_los_clientes.zip">aquí</a>.</p> </div> <div class="field field--name-field-funciones-dax-involucradas field--type-entity-reference field--label-above"> <div class="field__label">Funciones DAX involucradas</div> <div class="field__items"> <div class="field__item"><a href="/es/taxonomy/term/69" hreflang="es">SELECTCOLUMNS</a></div> <div class="field__item"><a href="/es/taxonomy/term/36" hreflang="es">FIRSTDATE</a></div> <div class="field__item"><a href="/es/taxonomy/term/35" hreflang="es">LASTDATE</a></div> <div class="field__item"><a href="/es/taxonomy/term/122" hreflang="es">DATEDIFF</a></div> <div class="field__item"><a href="/es/taxonomy/term/71" hreflang="es">RELATEDTABLE</a></div> <div class="field__item"><a href="/es/taxonomy/term/67" hreflang="es">COUNTROWS</a></div> <div class="field__item"><a href="/es/taxonomy/term/45" hreflang="es">DIVIDE</a></div> </div> </div> <div class="field field--name-field-dax-esc-dificultad field--type-list-string field--label-above"> <div class="field__label">Dificultad</div> <div class="field__item">Intermedia</div> </div> Mon, 14 Oct 2019 10:50:28 +0000 admin 1482 at https://interactivechaos.ovh Cálculo de la anterior fecha de compra para cada compra de cada cliente https://interactivechaos.ovh/es/dax/scenario/calculo-de-la-anterior-fecha-de-compra-para-cada-compra-de-cada-cliente <span class="field field--name-title field--type-string field--label-hidden">Cálculo de la anterior fecha de compra para cada compra de cada cliente</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/es/user/1" typeof="schema:Person" property="schema:name" datatype="">admin</span></span> <span class="field field--name-created field--type-created field--label-hidden">Sáb, 06/07/2019 - 20:23</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>Partimos de una tabla de ventas ("<em>Movements</em>") en la que figura la fecha de venta, el identificador del usuario y el importe de venta:</p> <img alt="Tabla de ventas" data-entity-type="file" data-entity-uuid="67229f85-0b0f-4009-b1d9-384ec4ac3a8f" src="/sites/default/files/inline-images/escenario-dax-0072.png" class="align-center" width="259" height="497" loading="lazy" /><p>Nuestro objetivo es añadir una nueva columna en la que se muestre la última compra del mismo cliente. Al recorrerse la tabla creándose el nuevo campo se creará para cada fila el contexto de fila asociado, lo que nos da acceso a los campos de la fila. Concretamente, la función <a href="/dax/function/earlier">EARLIER</a> nos permite acceder al identificador del cliente y a la fecha, de forma que podemos calcular el subconjunto de la tabla que contiene las compras del cliente actual anteriores a la fecha actual con la siguiente expresión:</p> <div class="codigo"> <p>FILTER(<br />     Movements;<br />     Movements[Customer Id] = EARLIER(Movements[Customer Id]) &amp;&amp;<br />     Movements[Order Date] &lt; EARLIER(Movements[Order Date])<br /> )</p> </div> <p>Una vez calculado este subconjunto, podemos extraer la última fecha muy fácilmente usando la función <a href="/dax/function/lastdate">LASTDATE</a>, función que devuelve una tabla con la última fecha del contexto actual. Usada como argumento de <a href="/dax/function/calculate">CALCULATE</a> y añadiendo como filtro el subconjunto calculado, podemos extraer la última fecha del conjunto (es decir, la última fecha de compra antes de la actual):</p> <div class="codigo"> <p>Last Purchase = <br />     CALCULATE(<br />         LASTDATE(Movements[Order Date]);<br />         FILTER(<br />             Movements;<br />             Movements[Customer Id] = EARLIER(Movements[Customer Id]) &amp;&amp;<br />             Movements[Order Date] &lt; EARLIER(Movements[Order Date])<br />         )<br />     )</p> </div> <p>Recordemos que, aunque la función LASTDATE devuelve una tabla, el resultado puede ser usado como un escalar allí donde se requiera una simple fecha. El resultado obtenido es el siguiente:</p> <img alt="Resultado obtenido" data-entity-type="file" data-entity-uuid="89501d32-a9ec-4177-a5ac-18dcba38df11" src="/sites/default/files/inline-images/escenario-dax-0073.png" class="align-center" width="585" height="554" loading="lazy" /><p>Podemos confirmar que el cálculo es correcto si llevamos a una visualización tipo tabla el identificador de usuario, el campo <em>Order Date</em> y el campo recién creado <em>Last Purchase</em>, filtrando el identificador de usuario (usando una segmentación, por ejemplo) y ordenando la tabla creada según el campo <em>Order Date</em>:</p> <img alt="Ventas para el cliente 19" data-entity-type="file" data-entity-uuid="5026e66a-ec6a-46ba-b942-408f7acdaa96" src="/sites/default/files/inline-images/escenario-dax-0074.png" class="align-center" width="489" height="271" loading="lazy" /><p>Vemos cómo la fecha de última compra coincide con la anterior.</p> </div> <div class="field field--name-field-funciones-dax-involucradas field--type-entity-reference field--label-above"> <div class="field__label">Funciones DAX involucradas</div> <div class="field__items"> <div class="field__item"><a href="/es/taxonomy/term/48" hreflang="es">FILTER</a></div> <div class="field__item"><a href="/es/taxonomy/term/89" hreflang="es">EARLIER</a></div> <div class="field__item"><a href="/es/taxonomy/term/33" hreflang="es">CALCULATE</a></div> <div class="field__item"><a href="/es/taxonomy/term/35" hreflang="es">LASTDATE</a></div> </div> </div> Sat, 06 Jul 2019 18:23:28 +0000 admin 1154 at https://interactivechaos.ovh Obtención de la fecha de la primera y última venta de cada vendedor https://interactivechaos.ovh/es/dax/scenario/obtencion-de-la-fecha-de-la-primera-y-ultima-venta-de-cada-vendedor <span class="field field--name-title field--type-string field--label-hidden">Obtención de la fecha de la primera y última venta de cada vendedor</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/es/user/1" typeof="schema:Person" property="schema:name" datatype="">admin</span></span> <span class="field field--name-created field--type-created field--label-hidden">Lun, 08/04/2019 - 11:50</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>En este sencillo escenario partimos de los siguientes datos:</p> <ul><li>Tabla de vendedores:</li> </ul><img alt="Tabla de vendedores" data-entity-type="file" data-entity-uuid="a31aa195-9f87-4a2e-b537-eb3fea9b2fad" src="/sites/default/files/inline-images/dax_function_0001.PNG" class="align-center" width="226" height="94" loading="lazy" /><ul><li>Tabla de ventas:</li> </ul><img alt="Tabla de ventas" data-entity-type="file" data-entity-uuid="76624da2-fe68-42d3-a4ee-7fd62a27825e" src="/sites/default/files/inline-images/dax_function_0002.PNG" class="align-center" width="606" height="156" loading="lazy" /><p>El objetivo es crear una tabla calculada en la que se incluya el nombre del vendedor y las fechas de su primera y última venta. Comencemos creando la tabla con los nombres, para lo que vamos a usar la función <a href="/dax/function/selectcolumns">SELECTCOLUMNS</a>:</p> <div class="codigo"> <p>Listado vendedores = SELECTCOLUMNS(<br />     Vendedores;<br />     "Nombre"; Vendedores[Nombre Vendedor]<br /> )</p> </div> <img alt="Listado de vendedores" data-entity-type="file" data-entity-uuid="bc6e090c-08b7-4c0f-b2f7-d1ed0731d599" src="/sites/default/files/inline-images/escenario-dax-0003.PNG" class="align-center" width="236" height="153" loading="lazy" /><p>Añadamos ahora la columna con la primera fecha de venta. Podríamos pensar en la necesidad de extraer mediante la función <a href="/dax/function/relatedtable">RELATEDTABLE</a> el subconjunto de la tabla de ventas asociada a cada fila de nuestra tabla (tal y como hacemos en el escenario de <a href="/dax/scenario/creacion-de-una-tabla-con-las-ventas-medias-por-vendedor">Creación de una tabla con las ventas medias por vendedor</a>) pero la función <a href="/dax/function/firstdate">FIRSTDATE</a>, tal y como podemos leer en la documentación, devuelve la primera fecha <strong>en el contexto actual</strong>, lo que supone el contexto de fila definido por cada vendedor, en nuestro caso, lo que hace innecesario el uso de la mencionada función RELATEDTABLE. Basta con usar FIRSTDATE de la siguiente forma:</p> <div class="codigo"> <p>Listado vendedores = SELECTCOLUMNS(<br />     Vendedores;<br />     "Nombre"; Vendedores[Nombre Vendedor];<br />     "Primera venta"; FIRSTDATE(Ventas[Fecha])<br /> )</p> </div> <img alt="Listado de vendedores y primera fecha de venta" data-entity-type="file" data-entity-uuid="87a43dbc-6379-4017-9d5b-b943975a3190" src="/sites/default/files/inline-images/escenario-dax-0004.PNG" class="align-center" width="387" height="157" loading="lazy" /><p>Vemos que las fechas son distintas, lo que ya nos indica que el cálculo de FIRSTDATE se realiza en contextos diferentes para cada fila. En todo caso comprobamos mediante una inspección ocular de la tabla de ventas que las fechas mostradas son las correctas.</p> <p>La adición de la última fecha de venta es análoga, utilizando la función <a href="/dax/function/lastdate">LASTDATE</a>:</p> <div class="codigo"> <p>Listado vendedores = SELECTCOLUMNS(<br />     Vendedores;<br />     "Nombre"; Vendedores[Nombre Vendedor];<br />     "Primera venta"; FIRSTDATE(Ventas[Fecha]);<br />     "Última venta"; LASTDATE(Ventas[Fecha])<br /> )</p> </div> <img alt="Listado de vendedores y primera y última fecha de venta" data-entity-type="file" data-entity-uuid="958fe5a6-6cdb-4cf8-bff3-cf406ae1651c" src="/sites/default/files/inline-images/escenario-dax-0005.PNG" class="align-center" width="330" height="141" loading="lazy" /><p> </p> </div> <div class="field field--name-field-funciones-dax-involucradas field--type-entity-reference field--label-above"> <div class="field__label">Funciones DAX involucradas</div> <div class="field__items"> <div class="field__item"><a href="/es/taxonomy/term/69" hreflang="es">SELECTCOLUMNS</a></div> <div class="field__item"><a href="/es/taxonomy/term/36" hreflang="es">FIRSTDATE</a></div> <div class="field__item"><a href="/es/taxonomy/term/35" hreflang="es">LASTDATE</a></div> </div> </div> Mon, 08 Apr 2019 09:50:20 +0000 admin 1041 at https://interactivechaos.ovh Análisis de la evolución de las ventas con una ventana de 14 días https://interactivechaos.ovh/es/dax/scenario/analisis-de-la-evolucion-de-las-ventas-con-una-ventana-de-14-dias <span class="field field--name-title field--type-string field--label-hidden">Análisis de la evolución de las ventas con una ventana de 14 días</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/es/user/1" typeof="schema:Person" property="schema:name" datatype="">admin</span></span> <span class="field field--name-created field--type-created field--label-hidden">Vie, 04/01/2019 - 15:04</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><p>En este escenario partimos de una tabla de ventas (<em>Sales</em>) en la que se indica, entre otros campos, la fecha y el importe de venta (<em>SalesAmount</em>). La medida <em>[Sales]</em> suma este última columna.</p> <p>El objetivo es llevar a una gráfica de líneas las ventas acumuladas durante las dos semanas previas para todas las fechas del calendario. Lo que necesitamos es calcular la medida <em>Sales</em> para el período de dos semanas de duración que termina en la fecha que se esté considerando en cada momento, es decir, en pseudo-código sería:</p> <div class="codigo"> <p>Fortnight sales = CALCULATE(</p> <p>    [Sales];</p> <p>    Período-de-dos-semanas-terminando-en-la-fecha-actual</p> <p>)</p> </div> <p>Como puede verse, utilizaremos la función <a href="/dax/function/calculate">CALCULATE </a>para evaluar la medida <em>Sales </em>en el período de interés.</p> <p>Para el cálculo del período de dos semanas que terminan en la fecha siendo considerada utilizaremos la función <a href="/dax/function/datesinperiod">DATESINPERIOD</a>, función que nos permite especificar la fecha de inicio de cálculo, el intervalo a añadir o restar (días en nuestro caso) y el número de intervalos a añadir o restar (14 en nuestro caso). Podríamos describir el período de interés de la siguiente forma:</p> <div class="codigo"> <p>Período-de-dos-semanas-terminando-en-la-fecha-actual = </p> <p>DATESINPERIOD(</p> <p>    'Calendar'[Date];</p> <p>    LASTDATE('Calendar'[Date]);</p> <p>    -14;</p> <p>DAY)</p> </div> <p>En nuestro ejemplo, la fecha de partida será la última del contexto (o la primera, pues se determinará según el contexto de fila ya que vamos a realizar nuestro cálculo para cada uno de los días por separado).</p> <p>Podemos, por lo tanto, definir la medida de la siguiente forma:</p> <div class="codigo"> <p>Fortnight sales = CALCULATE(</p> <p>    [Sales];</p> <p>    DATESINPERIOD(</p> <p>        'Calendar'[Date];</p> <p>        FIRSTDATE('Calendar'[Date]);</p> <p>        -14;</p> <p>        DAY</p> <p>    )</p> <p>)</p> </div> <p>Si llevamos a una tabla la columna del calendario conteniendo las fechas (<em>'Calendar'[Date]</em>) y la recién creada medida, obtenemos el siguiente resultado:</p> <img alt="Tabla mostrando las ventas acumuladas en ventas de 2 semanas" data-entity-type="file" data-entity-uuid="04717648-30bd-460e-8253-3ce85a78b479" src="/sites/default/files/inline-images/dax_scenario_ventas_2_semanas_01.jpg" class="align-center" width="625" height="670" loading="lazy" /><p>Puede comprobarse como, lógicamente, los 13 primeros días muestran acumulados parciales al no existir fechas anteriores al 1 de julio de 2001.</p> <p>Si llevamos estos mismos campos a un gráfico de líneas, el resultado es el siguiente:</p> <img alt="Gráfico mostrando el acumulado de ventas en ventanas de 2 semanas" data-entity-type="file" data-entity-uuid="0d385c59-bec5-4ba0-9742-689bc429b6b0" src="/sites/default/files/inline-images/dax_scenario_ventas_2_semanas_02.jpg" class="align-center" width="932" height="405" loading="lazy" /></div> <div class="field field--name-field-funciones-dax-involucradas field--type-entity-reference field--label-above"> <div class="field__label">Funciones DAX involucradas</div> <div class="field__items"> <div class="field__item"><a href="/es/taxonomy/term/33" hreflang="es">CALCULATE</a></div> <div class="field__item"><a href="/es/taxonomy/term/34" hreflang="es">DATESINPERIOD</a></div> <div class="field__item"><a href="/es/taxonomy/term/35" hreflang="es">LASTDATE</a></div> <div class="field__item"><a href="/es/taxonomy/term/36" hreflang="es">FIRSTDATE</a></div> </div> </div> Fri, 04 Jan 2019 14:04:36 +0000 admin 342 at https://interactivechaos.ovh