La función TOPN devuelve un subconjunto de una cantidad determinada de las primeras filas pertenecientes a una tabla, en base a una expresión utilizada para ordenar dicha tabla.
Como primer parámetro pasaremos el número de filas a recuperar; en segundo lugar indicaremos la tabla de la que se obtendrán las filas; el tercer parámetro corresponderá a la expresión que realizará la ordenación de las filas; y opcionalmente, en el cuarto parámetro, pasaremos un número (0 ó 1) indicativo del sentido (ascendente o descendente) en que se realizará la ordenación especificada en el tercer parámetro.
Supongamos que de la tabla DimProduct queremos averiguar las siete marcas de productos (columna BrandName) que han generado más ventas (tabla FactSales, columna SalesAmount). Comenzaremos nuestro análisis del problema desde el motor relacional, ejecutando la siguiente consulta SQL, que nos devuelve todas las marcas de producto con sus totales de venta correspondientes.
WITH tblMarcas AS ( SELECT DP.BrandName, SUM(FS.SalesAmount) AS VentasMarca FROM FactSales AS FS, DimProduct AS DP WHERE FS.ProductKey = DP.ProductKey GROUP BY DP.BrandName ) SELECT BrandName, FORMAT(VentasMarca, 'C', 'es-es') AS Ventas FROM tblMarcas ORDER BY VentasMarca DESC
Para obtener aquí las siete marcas con más ventas, simplemente añadiremos la partícula TOP junto a la cantidad de filas que necesitamos obtener.
WITH tblMarcas AS ( SELECT DP.BrandName, SUM(FS.SalesAmount) AS VentasMarca FROM FactSales AS FS, DimProduct AS DP WHERE FS.ProductKey = DP.ProductKey GROUP BY DP.BrandName ) SELECT TOP 7 BrandName, FORMAT(VentasMarca, 'C', 'es-es') AS Ventas FROM tblMarcas ORDER BY VentasMarca DESC
Vamos a realizar un primer intento para conseguir este mismo resultado en DAX, utilizando la función TOPN en la siguiente consulta.
EVALUATE TOPN( 7, VALUES('DimProduct'[BrandName]), SUM('FactSales'[SalesAmount]), 0 )
Los resultados, no obstante, no serán nada satisfactorios porque, por un lado, obtenemos todos los nombres de marcas de producto, y por otro, no aparecen los importes de ventas por marca. Observando detenidamente la documentación de la función veremos que esto es completamente lógico, ya que TOPN devuelve las filas de la tabla pasada en el segundo parámetro según el resultado de aplicar la expresión del tercero.
Como primer paso para acercarnos a la solución añadiremos a la consulta una medida calculada, que será la encargada de sumar la columna SalesAmount; esta medida la emplearemos a continuación como tercer parámetro de TOPN.
DEFINE MEASURE DimProduct[VentasPorMarca] = SUM(FactSales[SalesAmount]) EVALUATE TOPN( 7, VALUES('DimProduct'[BrandName]), DimProduct[VentasPorMarca], 0 )
Con esto casi hemos cumplido con nuestro objetivo, tan sólo nos falta visualizar la columna con los importes de ventas, para lo cual recurriremos a la función ADDCOLUMNS, a la que pasaremos como parámetro la función TOPN y la expresión con la columna calculada que realiza la suma de las ventas.
DEFINE MEASURE 'DimProduct'[VentasPorMarca] = SUM('FactSales' [SalesAmount]) EVALUATE ADDCOLUMNS( TOPN( 7, VALUES('DimProduct'[BrandName]), 'DimProduct'[VentasPorMarca], 0 ), "Ventas por nombre marca", FORMAT('DimProduct'[VentasPorMarca], "Currency") ) ORDER BY 'DimProduct'[VentasPorMarca] DESC
Aunque podamos estar acostumbrados al uso de la partícula TOP en Transact-SQL, en el contexto de las consultas y expresiones con DAX es probable que el empleo de TOPN no resulte tan intuitivo como a priori cabría esperar. En este enlace se proporciona una explicación más detallada sobre dicha función, y en este post se muestra un interesante caso de uso.
kiquenet
Muy buena serie, Luismi !
lmblanco
Hola Enrique
Muchas gracias por tu opinión y celebro que te estén gustando los post sobre este tema. En próximos días iré añadiendo alguno más 🙂
Un saludo,
Luismi