<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://geeks.ms/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>El aprendiz de brujo  : DAX, PowerPivot</title><link>http://geeks.ms/blogs/lmblanco/archive/tags/DAX/PowerPivot/default.aspx</link><description>Etiquetas: DAX, PowerPivot</description><dc:language /><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>Totales parciales con SUMMARIZE. Profundizando en el uso de DAX como lenguaje de consulta (y 9)</title><link>http://geeks.ms/blogs/lmblanco/archive/2013/05/15/totales-parciales-con-summarize-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-y-9.aspx</link><pubDate>Wed, 15 May 2013 17:16:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:209473</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=209473</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=209473</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2013/05/15/totales-parciales-con-summarize-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-y-9.aspx#comments</comments><description>&lt;p&gt;La cl&amp;aacute;usula &lt;a href="http://technet.microsoft.com/en-us/library/gg492171.aspx"&gt;ROLLUP&lt;/a&gt; perteneciente a la funci&amp;oacute;n SUMMARIZE genera, en las columnas de agregaci&amp;oacute;n que especifiquemos, filas adicionales de resultados acumulados (totales parciales) para las columnas num&amp;eacute;ricas utilizadas en la consulta.&lt;/p&gt;
&lt;p&gt;A modo de ejemplo, en la siguiente consulta utilizamos ROLLUP para la columna StoreType de la tabla DimStore, por lo que obtendremos, adem&amp;aacute;s de las cifras de venta por tipo de almac&amp;eacute;n, una &amp;uacute;ltima fila adicional con el total de las ventas.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ROLLUP(&amp;#39;DimStore&amp;#39;[StoreType]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[SalesAmount]) &lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_32.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Partiendo de este resultado, supongamos ahora que necesitamos que los tipos de almac&amp;eacute;n aparezcan ordenados, pero manteniendo la fila de total al final. Si usamos la cl&amp;aacute;usula ORDER BY en la consulta, el resultado no ser&amp;aacute; totalmente satisfactorio, ya que&amp;nbsp; se ordenar&amp;aacute;n los nombres, pero la fila de total quedar&amp;aacute; al principio.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ROLLUP(&amp;#39;DimStore&amp;#39;[StoreType]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[SalesAmount])&lt;br /&gt;)&lt;br /&gt;ORDER BY [StoreType]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_33.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Aplicando el modificador DESC a la cl&amp;aacute;usula ORDER BY solucionamos el problema solamente en parte, ya que conseguimos que el total vuelva a colocarse al final del conjunto de resultados, pero como es l&amp;oacute;gico, los nombres quedan ordenados en sentido descendente.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ROLLUP(&amp;#39;DimStore&amp;#39;[StoreType]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[SalesAmount])&lt;br /&gt;)&lt;br /&gt;ORDER BY [StoreType] DESC&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_34.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Controlando la ubicaci&amp;oacute;n de los acumulados mediante ISSUBTOTAL&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Si queremos ordenar los nombres en sentido ascendente, pero manteniendo la ubicaci&amp;oacute;n del total al final, debemos recurrir a &lt;a href="http://technet.microsoft.com/en-us/library/gg492171.aspx"&gt;ISSUBTOTAL&lt;/a&gt;, otra de las cl&amp;aacute;usulas de SUMMARIZE, la cual crea una columna de tipo l&amp;oacute;gico, en la que cada valor nos indica si la fila actual del conjunto de resultados corresponde a un acumulado (total parcial) o bien se trata de una fila normal de datos. El truco en este caso reside en aplicar una doble ordenaci&amp;oacute;n: primero por la columna de ISSUBTOTAL y a continuaci&amp;oacute;n por la de datos.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ROLLUP(&amp;#39;DimStore&amp;#39;[StoreType]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[SalesAmount]),&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Subtotal_StoreType&amp;quot;, ISSUBTOTAL(&amp;#39;DimStore&amp;#39;[StoreType])&lt;br /&gt;)&lt;br /&gt;ORDER BY [Subtotal_StoreType],[StoreType]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_35.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Ahora vamos a a&amp;ntilde;adir la columna ContinentName, de la tabla DimGeography, como nueva columna de agrupaci&amp;oacute;n a la consulta. De esta manera, cada fila de acumulado resultante se corresponder&amp;aacute; con el total de ventas de un continente para todos los tipos de almac&amp;eacute;n.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ROLLUP(&amp;#39;DimStore&amp;#39;[StoreType]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;[ContinentName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[SalesAmount])&lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_36.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;La interpretaci&amp;oacute;n de los datos que obtenemos, no obstante, es poco amigable, por lo que nuevamente usaremos ISSUBTOTAL y ordenaremos las columnas tal y como muestra el siguiente bloque de c&amp;oacute;digo, consiguiendo que las filas de acumulado se sit&amp;uacute;en proporcionando la informaci&amp;oacute;n de un modo m&amp;aacute;s legible.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ROLLUP(&amp;#39;DimStore&amp;#39;[StoreType]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;[ContinentName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[SalesAmount]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Subtotal_StoreType&amp;quot;, ISSUBTOTAL(&amp;#39;DimStore&amp;#39;[StoreType])&lt;br /&gt;)&lt;br /&gt;ORDER BY [ContinentName], [Subtotal_StoreType], [StoreType]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_37.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Ya que ROLLUP admite m&amp;aacute;s de una columna de agregaci&amp;oacute;n como par&amp;aacute;metro, vamos a a&amp;ntilde;adirle la columna ContinentName para obtener en esta ocasi&amp;oacute;n, adem&amp;aacute;s de los acumulados anteriormente mencionados, una nueva fila de total con el importe de las ventas para todos los tipos de almac&amp;eacute;n y continentes. Al mismo tiempo crearemos con ISSUBTOTAL sendas columnas para StoreType y ContinentName, que junto a un adecuado orden facilitar&amp;aacute;n la lectura de los datos.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ROLLUP(&amp;#39;DimStore&amp;#39;[StoreType], &amp;#39;DimGeography&amp;#39;[ContinentName]),&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[SalesAmount]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Subtotal_StoreType&amp;quot;, ISSUBTOTAL(&amp;#39;DimStore&amp;#39;[StoreType]),&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Subtotal_ContinentName&amp;quot;, ISSUBTOTAL(&amp;#39;DimGeography&amp;#39;[ContinentName])&lt;br /&gt;)&lt;br /&gt;ORDER BY [Subtotal_StoreType], [StoreType], [Subtotal_ContinentName], [ContinentName]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_38.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Agrupar los acumulados con ROLLUPGROUP&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;A pesar de existir la posibilidad de utilizar varias columnas con ROLLUP, en determinadas situaciones quiz&amp;aacute; nos interese tener una &amp;uacute;nica fila de acumulado para todas las columnas de agregaci&amp;oacute;n incluidas en esta cl&amp;aacute;usula, lo que podemos lograr&amp;nbsp; mediante &lt;a href="http://technet.microsoft.com/en-us/library/gg492171.aspx"&gt;ROLLUPGROUP&lt;/a&gt;, otra de las cl&amp;aacute;usulas de SUMMARIZE.&lt;/p&gt;
&lt;p&gt;Esta cl&amp;aacute;usula se utiliza como par&amp;aacute;metro de ROLLUP, colocando las columnas de agregaci&amp;oacute;n como par&amp;aacute;metros de la llamada a la funci&amp;oacute;n ROLLUPGROUP.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ROLLUP(ROLLUPGROUP(&amp;#39;DimStore&amp;#39;[StoreType], &amp;#39;DimGeography&amp;#39;[ContinentName])),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[SalesAmount]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Subtotal_StoreType&amp;quot;, ISSUBTOTAL(&amp;#39;DimStore&amp;#39;[StoreType])&lt;br /&gt;)&lt;br /&gt;ORDER BY [Subtotal_StoreType], [StoreType], [ContinentName]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_39.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Cabe destacar que la informaci&amp;oacute;n sobre ROLLUPGROUP disponible en la documentaci&amp;oacute;n online de la funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/gg492171.aspx"&gt;SUMMARIZE&lt;/a&gt; es una aportaci&amp;oacute;n de &lt;a href="http://sqlblog.com/blogs/marco_russo/"&gt;Marco Russo&lt;/a&gt;, puesto que dicha entrada, correspondiente a la &lt;a href="http://technet.microsoft.com/en-us/library/ee634396.aspx"&gt;referencia&lt;/a&gt; de las funciones del lenguaje DAX, no dispon&amp;iacute;a inicialmente de rese&amp;ntilde;a alguna acerca de esta cl&amp;aacute;usula.&lt;/p&gt;
&lt;p&gt;Para lograr un comportamiento similar en Transact-SQL haremos uso del operador ROLLUP cuando especifiquemos las columnas a agrupar, as&amp;iacute; como de la funci&amp;oacute;n GROUPING en la lista de columnas a mostrar de la instrucci&amp;oacute;n SELECT.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SELECT&lt;br /&gt;CASE&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN (GROUPING(StoreType)=1) THEN &amp;#39;--Total General--&amp;#39;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ELSE StoreType&lt;br /&gt;END AS StoreType,&lt;br /&gt;CASE&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN (GROUPING(ContinentName)=1) THEN &amp;#39;--Acumulado por tipo almac&amp;eacute;n--&amp;#39;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ELSE ContinentName&lt;br /&gt;END AS ContinentName,&lt;br /&gt;SUM(SalesAmount) AS Ventas&lt;br /&gt;FROM DimStore&lt;br /&gt;INNER JOIN DimGeography&lt;br /&gt;ON DimStore.GeographyKey = DimGeography.GeographyKey&lt;br /&gt;INNER JOIN FactSales&lt;br /&gt;ON DimStore.StoreKey = FactSales.StoreKey&lt;br /&gt;GROUP BY StoreType, ContinentName WITH ROLLUP&lt;br /&gt;ORDER BY StoreType, GROUPING(ContinentName), ContinentName&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Y llegados a este punto damos por concluida esta serie de art&amp;iacute;culos en los que hemos expuesto diversas t&amp;eacute;cnicas para la creaci&amp;oacute;n de consultas contra modelos tabulares empleando el lenguaje DAX, espero que os resulten de utilidad.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=209473" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/BISM/default.aspx">BISM</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server+2012/default.aspx">SQL Server 2012</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Tabular+Model/default.aspx">Tabular Model</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>Columnas de agrupación en SUMMARIZE con tablas no relacionadas. Profundizando en el uso de DAX como lenguaje de consulta (8)</title><link>http://geeks.ms/blogs/lmblanco/archive/2013/05/07/columnas-de-agrupaci-243-n-en-summarize-con-tablas-no-relacionadas-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-8.aspx</link><pubDate>Tue, 07 May 2013 18:45:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:209414</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=209414</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=209414</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2013/05/07/columnas-de-agrupaci-243-n-en-summarize-con-tablas-no-relacionadas-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-8.aspx#comments</comments><description>&lt;p&gt;Si las tablas de las columnas empleadas en la consulta con SUMMARIZE no est&amp;aacute;n relacionadas se producir&amp;aacute; un error, como vemos en el siguiente bloque de c&amp;oacute;digo, donde combinamos las columnas StoreType y BrandName de las tablas DimStore y DimProduct, para obtener las ventas realizadas.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;[StoreType],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimProduct&amp;#39;[BrandName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[SalesAmount])&lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_27.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Tal y como se explica en el mensaje de error, la columna BrandName no existe en la tabla de entrada DimStore, utilizada como primer par&amp;aacute;metro de la funci&amp;oacute;n SUMMARIZE; aunque en este caso ser&amp;iacute;a m&amp;aacute;s correcto decir que la tabla DimProduct, que contiene la columna BrandName, no est&amp;aacute; relacionada con la tabla de entrada usada en la consulta. &lt;/p&gt;
&lt;p&gt;Si el primer par&amp;aacute;metro de SUMMARIZE representa una tabla con las columnas a visualizar (directa o indirectamente a trav&amp;eacute;s de relaciones), en el caso de que no existan relaciones con las tablas necesarias podemos crear una tabla al vuelo con las columnas que tenemos que mostrar empleando la funci&amp;oacute;n GENERATE.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GENERATE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimStore&amp;#39;[StoreType]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [StoreType],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [BrandName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas tipo almac&amp;eacute;n marca producto&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[SalesAmount])&lt;br /&gt;)&lt;br /&gt;ORDER BY [StoreType],[BrandName]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_28.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En el caso de que el n&amp;uacute;mero de columnas sin relacionar que tengamos que presentar sea superior a dos, podemos optar por la funci&amp;oacute;n CROSSJOIN para crear la tabla de entrada utilizada por SUMMARIZE, como vemos en la siguiente consulta, donde creamos una medida calculada para realizar la suma de las ventas, a la que aplicaremos un formato monetario, y que emplearemos en una condici&amp;oacute;n de filtro para evitar mostrar importes vac&amp;iacute;os.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;DEFINE&lt;br /&gt;MEASURE &amp;#39;FactSales&amp;#39;[Ventas] = SUM(&amp;#39;FactSales&amp;#39;[SalesAmount])&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;FILTER(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CROSSJOIN(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimStore&amp;#39;[StoreType]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimDate&amp;#39;[CalendarYear])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [StoreType],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [BrandName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [CalendarYear],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas tipo almac&amp;eacute;n-marca producto-a&amp;ntilde;o venta&amp;quot;, FORMAT(&amp;#39;FactSales&amp;#39;[Ventas], &amp;quot;Currency&amp;quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NOT(ISBLANK([Ventas]))&lt;br /&gt;)&lt;br /&gt;ORDER BY [StoreType],[BrandName],[CalendarYear]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_29.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Partiendo del anterior resultado, supongamos ahora que necesitamos calcular el porcentaje que la combinaci&amp;oacute;n de ventas por tipo de almac&amp;eacute;n, marca de producto y a&amp;ntilde;o de venta ha supuesto con respecto al total de las ventas realizadas.&lt;/p&gt;
&lt;p&gt;Para obtener estos resultados precisamos a&amp;ntilde;adir al c&amp;oacute;digo de la consulta dos nuevas medidas calculadas: la primera, a la que llamaremos VentasTotales, realizar&amp;aacute; mediante la funci&amp;oacute;n SUMX la suma de la columna SalesAmount para todas las filas de la tabla FactSales; empleando la funci&amp;oacute;n ALL para ignorar cualquier filtro que pudiera encontrarse activo.&lt;/p&gt;
&lt;p&gt;La segunda medida, PorcentajeVentas, efectuar&amp;aacute; la operaci&amp;oacute;n encargada de calcular el porcentaje de las ventas realizadas. Dicho valor ser&amp;aacute; convenientemente formateado cuando lo mostremos junto al resto de columnas de la consulta.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;DEFINE&lt;br /&gt;MEASURE &amp;#39;FactSales&amp;#39;[Ventas] = SUM(&amp;#39;FactSales&amp;#39;[SalesAmount])&lt;br /&gt;MEASURE &amp;#39;FactSales&amp;#39;[VentasTotales] = SUMX(ALL(&amp;#39;FactSales&amp;#39;), &amp;#39;FactSales&amp;#39;[SalesAmount]) &lt;br /&gt;MEASURE &amp;#39;FactSales&amp;#39;[PorcentajeVentas] = (&amp;#39;FactSales&amp;#39;[Ventas] / &amp;#39;FactSales&amp;#39;[VentasTotales])&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;FILTER(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CROSSJOIN(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimStore&amp;#39;[StoreType]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimDate&amp;#39;[CalendarYear])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [StoreType],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [BrandName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [CalendarYear],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas tipo almac&amp;eacute;n-marca producto-a&amp;ntilde;o venta&amp;quot;, FORMAT(&amp;#39;FactSales&amp;#39;[Ventas], &amp;quot;Currency&amp;quot;),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas totales&amp;quot;, &amp;#39;FactSales&amp;#39;[VentasTotales],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Porcentaje ventas&amp;quot;, FORMAT(&amp;#39;FactSales&amp;#39;[PorcentajeVentas], &amp;quot;Percent&amp;quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NOT(ISBLANK([Ventas]))&lt;br /&gt;)&lt;br /&gt;ORDER BY [StoreType],[BrandName],[CalendarYear]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_30.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Aunque la medida calculada VentasTotales se visualiza junto al resto de las columnas, podr&amp;iacute;a perfectamente permanecer oculta, ya que su finalidad consiste en actuar como operando para hallar el porcentaje de las ventas.&lt;/p&gt;
&lt;p&gt;Para obtener este mismo resultado mediante SQL, tendremos que establecer, al igual que en anteriores ejemplos, las combinaciones necesarias entre las tablas implicadas en la consulta.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SELECT StoreType, BrandName, CalendarYear,&lt;br /&gt;SUM(SalesAmount) AS [Ventas tipo almac&amp;eacute;n-marca producto-a&amp;ntilde;o venta],&lt;br /&gt;(SELECT SUM(SalesAmount) FROM FactSales) AS [Ventas totales],&lt;br /&gt;FORMAT( ( SUM(SalesAmount) / (SELECT SUM(SalesAmount) FROM FactSales) ) , &amp;#39;P&amp;#39;, &amp;#39;ES-ES&amp;#39; )&amp;nbsp; AS [Porcentaje ventas]&lt;br /&gt;FROM DimStore&lt;br /&gt;INNER JOIN FactSales&lt;br /&gt;ON DimStore.StoreKey = FactSales.StoreKey&lt;br /&gt;INNER JOIN DimProduct&lt;br /&gt;ON FactSales.ProductKey = DimProduct.ProductKey&lt;br /&gt;INNER JOIN DimDate&lt;br /&gt;ON FactSales.DateKey = DimDate.Datekey&lt;br /&gt;GROUP BY StoreType, BrandName, CalendarYear&lt;br /&gt;ORDER BY StoreType, BrandName, CalendarYear&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Empleando la tabla de resultados num&amp;eacute;ricos como tabla de entrada&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;En los &amp;uacute;ltimos ejemplos de SUMMARIZE hemos planteado la manera de abordar la creaci&amp;oacute;n de una consulta introduciendo un problema consistente en la inexistencia de relaciones entre la tabla de entrada y el resto de tablas de las columnas de agregaci&amp;oacute;n implicadas en dicha consulta, lo cual nos llevaba a recurrir a soluciones un tanto artificiosas, tales como el empleo de las funciones GENERATE o CROSSJOIN en el c&amp;oacute;digo a escribir.&lt;/p&gt;
&lt;p&gt;Observando las caracter&amp;iacute;sticas de estas consultas nos percataremos de que la tabla FactSales, empleada para calcular la suma de ventas, se encuentra relacionada con las tablas utilizadas para las columnas de agregaci&amp;oacute;n. Si a esto unimos la capacidad de utilizar FactSales como tabla de entrada en SUMMARIZE, podremos construir una consulta m&amp;aacute;s simple que evite el uso de trucos rebuscados. Como ventaja a&amp;ntilde;adida, esta consulta no devuelve filas con la columna de ventas vac&amp;iacute;a, lo que tambi&amp;eacute;n nos libera de aplicar el correspondiente filtro.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;FactSales&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;[StoreType],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimProduct&amp;#39;[BrandName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimDate&amp;#39;[CalendarYear],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas&amp;quot;, FORMAT(SUM(&amp;#39;FactSales&amp;#39;[SalesAmount]), &amp;quot;Currency&amp;quot;)&lt;br /&gt;)&lt;br /&gt;ORDER BY [StoreType],[BrandName],[CalendarYear]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_31.jpg" border="0" style="max-width:550px;" alt="" /&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=209414" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/BISM/default.aspx">BISM</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server+2012/default.aspx">SQL Server 2012</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Tabular+Model/default.aspx">Tabular Model</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>Combinación de múltiples tablas con SUMMARIZE. Profundizando en el uso de DAX como lenguaje de consulta (7)</title><link>http://geeks.ms/blogs/lmblanco/archive/2013/04/24/combinaci-243-n-de-m-250-ltiples-tablas-con-summarize-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-7.aspx</link><pubDate>Wed, 24 Apr 2013 17:59:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:209278</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=209278</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=209278</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2013/04/24/combinaci-243-n-de-m-250-ltiples-tablas-con-summarize-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-7.aspx#comments</comments><description>&lt;p&gt;Las columnas de agrupaci&amp;oacute;n de los ejemplos con SUMMARIZE mostrados en la entrega anterior pertenec&amp;iacute;an a una misma tabla, lo cual puede resultar conveniente en determinados casos, pero con toda seguridad, en alg&amp;uacute;n momento nos encontraremos ante situaciones en las que tengamos que crear una consulta para visualizar columnas pertenecientes a diversas tablas del modelo.&lt;/p&gt;
&lt;p&gt;Gracias a la potencia que ofrece el mecanismo de relaciones del motor tabular, esta labor resulta tan simple como a&amp;ntilde;adir tales columnas en la lista de par&amp;aacute;metros de la funci&amp;oacute;n, siempre y cuando existan las oportunas relaciones entre las tablas integrantes de la consulta.&lt;/p&gt;
&lt;p&gt;Observando el diagrama de nuestro modelo de datos de ejemplo vemos que la tabla DimStore se relaciona con las tablas DimGeography, DimEmployee y FactSales, por lo que podemos construir una consulta con SUMMARIZE en la que ofrezcamos al usuario la suma de los descuentos sobre las ventas, agregada por el tipo de almac&amp;eacute;n, pa&amp;iacute;s y nombre del gerente del almac&amp;eacute;n que ha realizado la venta.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;[StoreType],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;[RegionCountryName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimEmployee&amp;#39;[FirstName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimEmployee&amp;#39;[LastName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Total descuentos&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[DiscountAmount])&lt;br /&gt;)&lt;br /&gt;ORDER BY [StoreType],[RegionCountryName],[FirstName],[LastName]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_25.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En SQL esta consulta es muy similar a la anterior que hemos escrito en Transact, con alguna variaci&amp;oacute;n en las tablas a combinar.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SELECT StoreType, RegionCountryName, FirstName, LastName,&lt;br /&gt;SUM(DiscountAmount) AS [Total descuentos]&lt;br /&gt;FROM DimStore&lt;br /&gt;INNER JOIN DimGeography&lt;br /&gt;ON DimStore.GeographyKey = DimGeography.GeographyKey&lt;br /&gt;INNER JOIN DimEmployee&lt;br /&gt;ON DimStore.StoreManager = DimEmployee.EmployeeKey&lt;br /&gt;INNER JOIN FactSales&lt;br /&gt;ON DimStore.StoreKey = FactSales.StoreKey&lt;br /&gt;GROUP BY StoreType, RegionCountryName, FirstName, LastName&lt;br /&gt;ORDER BY StoreType, RegionCountryName, FirstName, LastName&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En la tabla DimStore, la columna StoreManager representa al empleado de la organizaci&amp;oacute;n que realiza las funciones de gerente o director del almac&amp;eacute;n, existiendo la posibilidad de que un mismo gerente se encuentre al cargo de varios almacenes. Esto nos permite complicar un poco la consulta DAX anterior, de manera que los resultados visualizados se correspondan con los directores que administran m&amp;aacute;s de un almac&amp;eacute;n.&lt;/p&gt;
&lt;p&gt;A continuaci&amp;oacute;n mostramos nuevamente esta consulta con los retoques que acabamos de mencionar. Por un lado quitamos la columna StoreType de la tabla DimStore, ya que uno de los objetivos consiste en contar el n&amp;uacute;mero de almacenes a cargo de cada director, independientemente del tipo de almac&amp;eacute;n. Dicho recuento lo realizaremos empleando una medida calculada (cl&amp;aacute;usula DEFINE) con el nombre NumeroAlmacenes, que reutilizaremos en m&amp;aacute;s de un lugar de la consulta. La funci&amp;oacute;n FILTER, por otra parte, nos permitir&amp;aacute; establecer la condici&amp;oacute;n para obtener los gerentes a cargo de varios almacenes. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;DEFINE&lt;br /&gt;MEASURE &amp;#39;DimStore&amp;#39;[NumeroAlmacenes] = COUNT(&amp;#39;DimStore&amp;#39;[StoreKey])&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;FILTER(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;[RegionCountryName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimEmployee&amp;#39;[FirstName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimEmployee&amp;#39;[LastName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Total descuentos&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[DiscountAmount]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;N&amp;uacute;mero almacenes gestionados&amp;quot;, &amp;#39;DimStore&amp;#39;[NumeroAlmacenes]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;[NumeroAlmacenes] &amp;gt; 1&lt;br /&gt;)&lt;br /&gt;ORDER BY [RegionCountryName],[FirstName],[LastName]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_26.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Utilizando SQL resulta necesario escribir una mayor cantidad de c&amp;oacute;digo para conseguir este mismo resultado, como vemos a continuaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;WITH&lt;br /&gt;tblGerentes AS&lt;br /&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT StoreManager, COUNT(*) AS NumeroAlmacenes&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM DimStore&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GROUP BY StoreManager&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HAVING COUNT(*) &amp;gt; 1&lt;br /&gt;),&lt;br /&gt;tblStore AS&lt;br /&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT StoreKey, GeographyKey, DimStore.StoreManager, tblGerentes.NumeroAlmacenes&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM DimStore&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; INNER JOIN tblGerentes&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ON DimStore.StoreManager = tblGerentes.StoreManager&lt;br /&gt;)&lt;br /&gt;SELECT RegionCountryName, StoreManager, FirstName, LastName,&lt;br /&gt;SUM(DiscountAmount) AS [Total descuentos],&lt;br /&gt;NumeroAlmacenes AS [N&amp;uacute;mero almacenes gestionados]&lt;br /&gt;FROM tblStore&lt;br /&gt;INNER JOIN DimGeography&lt;br /&gt;ON tblStore.GeographyKey = DimGeography.GeographyKey&lt;br /&gt;INNER JOIN DimEmployee&lt;br /&gt;ON tblStore.StoreManager = DimEmployee.EmployeeKey&lt;br /&gt;INNER JOIN FactSales&lt;br /&gt;ON tblStore.StoreKey = FactSales.StoreKey&lt;br /&gt;GROUP BY RegionCountryName, StoreManager, FirstName, LastName, NumeroAlmacenes&lt;br /&gt;ORDER BY RegionCountryName, StoreManager, FirstName, LastName, NumeroAlmacenes&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En la siguiente entrega daremos otra vuelta de tuerca al uso de la funci&amp;oacute;n SUMMARIZE, mostrando el modo de resolver consultas en las que se encuentren involucradas tablas no relacionadas.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=209278" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/BISM/default.aspx">BISM</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server+2012/default.aspx">SQL Server 2012</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Tabular+Model/default.aspx">Tabular Model</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>Agrupación y agregación de columnas con la función SUMMARIZE. Profundizando en el uso de DAX como lenguaje de consulta (6)</title><link>http://geeks.ms/blogs/lmblanco/archive/2013/04/17/agrupaci-243-n-y-agregaci-243-n-de-columnas-con-la-funci-243-n-summarize-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-6.aspx</link><pubDate>Wed, 17 Apr 2013 17:29:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:209207</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=209207</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=209207</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2013/04/17/agrupaci-243-n-y-agregaci-243-n-de-columnas-con-la-funci-243-n-summarize-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-6.aspx#comments</comments><description>&lt;p&gt;La funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/gg492171.aspx"&gt;SUMMARIZE&lt;/a&gt; muestra los distintos valores de una o varias columnas (denominadas &lt;i&gt;columnas de agrupaci&amp;oacute;n&lt;/i&gt;) de una tabla, permitiendo adem&amp;aacute;s incluir expresiones que generen columnas calculadas, encargadas de devolver valores num&amp;eacute;ricos en base a las columnas de agrupaci&amp;oacute;n. Con ello logramos un comportamiento similar al obtenido mediante la cl&amp;aacute;usula GROUP BY de Transact-SQL.&lt;/p&gt;
&lt;p&gt;Comenzaremos nuestro periplo acerca del uso de esta funci&amp;oacute;n con un ejemplo muy b&amp;aacute;sico: mostrar los distintos valores de la columna RegionCountryName, perteneciente a la tabla DimGeography.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;[RegionCountryName]&lt;br /&gt;)&lt;br /&gt;ORDER BY [RegionCountryName]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_23.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Como es l&amp;oacute;gico, podemos utilizar varias de las columnas correspondientes a la tabla pasada en el primer par&amp;aacute;metro, tambi&amp;eacute;n denominada &lt;i&gt;tabla de entrada&lt;/i&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;[ContinentName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;[RegionCountryName]&lt;br /&gt;)&lt;br /&gt;ORDER BY [ContinentName],[RegionCountryName]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Para conseguir un resultado equivalente en SQL podemos emplear GROUP BY, tal y como hemos mencionado anteriormente, o tambi&amp;eacute;n la cl&amp;aacute;usula DISTINCT, ya que hasta el momento no estamos usando una operaci&amp;oacute;n de agregado como COUNT, SUM, etc., sobre el conjunto de resultados.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SELECT ContinentName, RegionCountryName &lt;br /&gt;FROM DimGeography&lt;br /&gt;GROUP BY ContinentName, RegionCountryName&lt;br /&gt;ORDER BY ContinentName, RegionCountryName&lt;/p&gt;
&lt;p&gt;--//////////////////////////////////////////////&lt;/p&gt;
&lt;p&gt;SELECT DISTINCT ContinentName, RegionCountryName &lt;br /&gt;FROM DimGeography&lt;br /&gt;ORDER BY ContinentName, RegionCountryName&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Supongamos ahora que de este resultado nos interesar&amp;iacute;a saber la cantidad de unidades vendidas para cada una de las combinaciones de continente y pa&amp;iacute;s. Para ello escribiremos una expresi&amp;oacute;n que utilice la funci&amp;oacute;n SUM aplicada a la columna SalesQuantity de la tabla FactSales, y que a&amp;ntilde;adiremos a SUMMARIZE como &amp;uacute;ltimo par&amp;aacute;metro.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;[ContinentName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;[RegionCountryName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Cantidades vendidas&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[SalesQuantity])&lt;br /&gt;)&lt;br /&gt;ORDER BY [ContinentName],[RegionCountryName]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_24.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En el caso de que necesitemos m&amp;aacute;s columnas calculadas iremos a&amp;ntilde;adiendo las expresiones correspondientes a las mismas como par&amp;aacute;metros adicionales al final de la funci&amp;oacute;n, tal y como vemos a continuaci&amp;oacute;n, donde agregamos dos medidas para obtener el importe de venta y las ventas menos el descuento aplicado.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;SUMMARIZE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;[ContinentName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimGeography&amp;#39;[RegionCountryName],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Cantidades vendidas&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[SalesQuantity]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Importe ventas&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[SalesAmount]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Venta con descuento&amp;quot;, SUMX(&amp;#39;FactSales&amp;#39;, &amp;#39;FactSales&amp;#39;[SalesAmount] - &amp;#39;FactSales&amp;#39;[DiscountAmount])&lt;br /&gt;)&lt;br /&gt;ORDER BY [ContinentName],[RegionCountryName]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Al emplear una sentencia SQL para obtener un resultado equivalente ahora s&amp;iacute; ser&amp;aacute; necesario el uso de GROUP BY, dado que aplicamos diversas operaciones de agregado (suma) sobre varias columnas, as&amp;iacute; como la combinaci&amp;oacute;n de la tabla DimGeography con DimStore y FactSales, para que las columnas num&amp;eacute;ricas reflejen los valores correctos para cada continente y pa&amp;iacute;s.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SELECT ContinentName, RegionCountryName,&lt;br /&gt;SUM(SalesQuantity) AS [Cantidades vendidas],&lt;br /&gt;SUM(SalesAmount) AS [Importe ventas],&lt;br /&gt;(SUM(SalesAmount) - SUM(DiscountAmount)) AS [Venta con descuento]&lt;br /&gt;FROM DimGeography&lt;br /&gt;INNER JOIN DimStore&lt;br /&gt;ON DimGeography.GeographyKey = DimStore.GeographyKey&lt;br /&gt;INNER JOIN FactSales&lt;br /&gt;ON DimStore.StoreKey = FactSales.StoreKey&lt;br /&gt;GROUP BY ContinentName, RegionCountryName&lt;br /&gt;ORDER BY ContinentName, RegionCountryName&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En la siguiente parte de esta serie abordaremos la forma de mostrar columnas de agrupaci&amp;oacute;n procedentes de m&amp;uacute;ltiples tablas empleando SUMMARIZE.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=209207" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/BISM/default.aspx">BISM</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server+2012/default.aspx">SQL Server 2012</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Tabular+Model/default.aspx">Tabular Model</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>Obtención de N filas con TOPN. Profundizando en el uso de DAX como lenguaje de consulta (5)</title><link>http://geeks.ms/blogs/lmblanco/archive/2013/04/10/obtenci-243-n-de-n-filas-con-topn-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-5.aspx</link><pubDate>Wed, 10 Apr 2013 20:53:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:209135</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=209135</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=209135</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2013/04/10/obtenci-243-n-de-n-filas-con-topn-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-5.aspx#comments</comments><description>&lt;p&gt;La funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/gg492198.aspx"&gt;TOPN&lt;/a&gt; devuelve un subconjunto de una cantidad determinada de las primeras filas pertenecientes a una tabla, en base a una expresi&amp;oacute;n utilizada para ordenar dicha tabla.&lt;/p&gt;
&lt;p&gt;Como primer par&amp;aacute;metro pasaremos el n&amp;uacute;mero de filas a recuperar; en segundo lugar indicaremos la tabla de la que se obtendr&amp;aacute;n las filas; el tercer par&amp;aacute;metro corresponder&amp;aacute; a la expresi&amp;oacute;n que realizar&amp;aacute; la ordenaci&amp;oacute;n de las filas; y opcionalmente, en el cuarto par&amp;aacute;metro, pasaremos un n&amp;uacute;mero (0 &amp;oacute; 1) indicativo del sentido (ascendente o descendente) en que se realizar&amp;aacute; la ordenaci&amp;oacute;n especificada en el tercer par&amp;aacute;metro.&lt;/p&gt;
&lt;p&gt;Supongamos que de la tabla DimProduct queremos averiguar las siete marcas de productos (columna BrandName) que han generado m&amp;aacute;s ventas (tabla FactSales, columna SalesAmount). Comenzaremos nuestro an&amp;aacute;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.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;WITH tblMarcas AS&lt;br /&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT DP.BrandName,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SUM(FS.SalesAmount) AS VentasMarca&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM FactSales AS FS, DimProduct AS DP&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE FS.ProductKey = DP.ProductKey&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GROUP BY DP.BrandName&lt;br /&gt;)&lt;br /&gt;SELECT BrandName, FORMAT(VentasMarca, &amp;#39;C&amp;#39;, &amp;#39;es-es&amp;#39;) AS Ventas&lt;br /&gt;FROM tblMarcas&lt;br /&gt;ORDER BY VentasMarca DESC&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_20.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Para obtener aqu&amp;iacute; las siete marcas con m&amp;aacute;s ventas, simplemente a&amp;ntilde;adiremos la part&amp;iacute;cula TOP junto a la cantidad de filas que necesitamos obtener.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;WITH tblMarcas AS&lt;br /&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT DP.BrandName,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SUM(FS.SalesAmount) AS VentasMarca&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM FactSales AS FS, DimProduct AS DP&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHERE FS.ProductKey = DP.ProductKey&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GROUP BY DP.BrandName&lt;br /&gt;)&lt;br /&gt;SELECT TOP 7 BrandName, FORMAT(VentasMarca, &amp;#39;C&amp;#39;, &amp;#39;es-es&amp;#39;) AS Ventas&lt;br /&gt;FROM tblMarcas&lt;br /&gt;ORDER BY VentasMarca DESC&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Vamos a realizar un primer intento para conseguir este mismo resultado en DAX, utilizando la funci&amp;oacute;n TOPN en la siguiente consulta.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;TOPN(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SUM(&amp;#39;FactSales&amp;#39;[SalesAmount]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0&lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Los resultados, no obstante, no ser&amp;aacute;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&amp;oacute;n de la funci&amp;oacute;n veremos que esto es completamente l&amp;oacute;gico, ya que TOPN devuelve las filas de la tabla pasada en el segundo par&amp;aacute;metro seg&amp;uacute;n el resultado de aplicar la expresi&amp;oacute;n del tercero.&lt;/p&gt;
&lt;p&gt;Como primer paso para acercarnos a la soluci&amp;oacute;n a&amp;ntilde;adiremos a la consulta una medida calculada, que ser&amp;aacute; la encargada de sumar la columna SalesAmount; esta medida la emplearemos a continuaci&amp;oacute;n como tercer par&amp;aacute;metro de TOPN.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;DEFINE&lt;br /&gt;MEASURE DimProduct[VentasPorMarca] = SUM(FactSales[SalesAmount])&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;TOPN(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DimProduct[VentasPorMarca],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0&lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_21.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Con esto casi hemos cumplido con nuestro objetivo, tan s&amp;oacute;lo nos falta visualizar la columna con los importes de ventas, para lo cual recurriremos a la funci&amp;oacute;n ADDCOLUMNS, a la que pasaremos como par&amp;aacute;metro la funci&amp;oacute;n TOPN y la expresi&amp;oacute;n con la columna calculada que realiza la suma de las ventas.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;DEFINE&lt;br /&gt;MEASURE &amp;#39;DimProduct&amp;#39;[VentasPorMarca] = SUM(&amp;#39;FactSales&amp;#39; [SalesAmount])&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TOPN(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimProduct&amp;#39;[VentasPorMarca],&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas por nombre marca&amp;quot;, FORMAT(&amp;#39;DimProduct&amp;#39;[VentasPorMarca], &amp;quot;Currency&amp;quot;)&lt;br /&gt;)&lt;br /&gt;ORDER BY &amp;#39;DimProduct&amp;#39;[VentasPorMarca] DESC&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_22.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Aunque podamos estar acostumbrados al uso de la part&amp;iacute;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&amp;iacute;a esperar. En este &lt;a href="http://www.powerpivotpro.com/2011/07/guest-post-topn-in-powerpivot-v2/"&gt;enlace&lt;/a&gt; se proporciona una explicaci&amp;oacute;n m&amp;aacute;s detallada sobre dicha funci&amp;oacute;n, y en este &lt;a href="http://bipassion.wordpress.com/2012/04/25/dax-topn-generate/"&gt;post&lt;/a&gt; se muestra un interesante caso de uso.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=209135" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/BISM/default.aspx">BISM</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server+2012/default.aspx">SQL Server 2012</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Tabular+Model/default.aspx">Tabular Model</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>La función CROSSJOIN. Profundizando en el uso de DAX como lenguaje de consulta (4)</title><link>http://geeks.ms/blogs/lmblanco/archive/2013/04/02/la-funci-243-n-crossjoin-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-4.aspx</link><pubDate>Tue, 02 Apr 2013 20:39:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:209032</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=209032</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=209032</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2013/04/02/la-funci-243-n-crossjoin-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-4.aspx#comments</comments><description>&lt;p&gt;A ra&amp;iacute;z de las consultas desarrolladas en la entrega anterior, supongamos que ahora debemos visualizar, adem&amp;aacute;s de la marca del producto y el a&amp;ntilde;o de venta, el nombre del pa&amp;iacute;s y tipo de almac&amp;eacute;n en el que &amp;eacute;sta se ha producido; datos que encontramos en las tablas DimGeography y DimStore respectivamente.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;CROSSJOIN. Aumentando la cantidad de tablas a combinar&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Puesto que la funci&amp;oacute;n GENERATE admite solamente dos tablas en su lista de par&amp;aacute;metros debemos modificar nuestra consulta, de forma que soporte la inclusi&amp;oacute;n de nuevas columnas, por lo que vamos a recurrir a la funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/gg492168.aspx"&gt;CROSSJOIN&lt;/a&gt;, que al igual que GENERATE, realiza un producto cartesiano de las tablas que recibe como par&amp;aacute;metro, pero con la diferencia de poder utilizar m&amp;aacute;s de dos tablas, como vemos en la siguiente consulta.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;CROSSJOIN(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimGeography&amp;#39;[ContinentName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimStore&amp;#39;[StoreType]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimDate&amp;#39;[CalendarYear])&lt;br /&gt;)&lt;br /&gt;ORDER BY [ContinentName], [StoreType], [BrandName], [CalendarYear]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_15.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Para obtener el mismo resultado en Transact-SQL podemos utilizar la cl&amp;aacute;usula CROSS JOIN, pero con el inconveniente de que el tiempo de ejecuci&amp;oacute;n de la consulta ser&amp;aacute; notablemente mayor que en DAX.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SELECT DISTINCT g.ContinentName,s.StoreType,p.BrandName,d.CalendarYear&lt;br /&gt;FROM DimGeography AS g&lt;br /&gt;CROSS JOIN DimStore AS s&lt;br /&gt;CROSS JOIN DimProduct AS p&lt;br /&gt;CROSS JOIN DimDate AS d&lt;br /&gt;ORDER BY g.ContinentName,s.StoreType,p.BrandName,d.CalendarYear&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Para a&amp;ntilde;adir a la consulta DAX la columna con las cifras de ventas emplearemos ADDCOLUMNS como uno m&amp;aacute;s de los par&amp;aacute;metros de CROSSJOIN.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;CROSSJOIN(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimGeography&amp;#39;[ContinentName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimStore&amp;#39;[StoreType]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimDate&amp;#39;[CalendarYear]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas&amp;quot;,FORMAT(SUMX(RELATEDTABLE(FactSales), &amp;#39;FactSales&amp;#39;[SalesAmount]), &amp;quot;Currency&amp;quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br /&gt;)&lt;br /&gt;ORDER BY [ContinentName], [StoreType], [BrandName], [CalendarYear]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_16.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Tras ejecutar la consulta, con toda seguridad habremos advertido que el c&amp;aacute;lculo resultante en la columna de ventas es incorrecto, ya que para cada fila &amp;uacute;nicamente se est&amp;aacute; teniendo en cuenta la columna &amp;#39;DimDate&amp;#39;[CalendarYear] al realizar la suma de &amp;#39;FactSales&amp;#39;[SalesAmount]. Este resultado para cada grupo de a&amp;ntilde;os es el mismo que si utiliz&amp;aacute;ramos la siguiente consulta SQL.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SELECT YEAR(DateKey) AS A&amp;ntilde;oVenta, &lt;br /&gt;FORMAT(SUM(SalesAmount), &amp;#39;C&amp;#39;, &amp;#39;es-es&amp;#39;) AS ImporteVentas&lt;br /&gt;FROM FactSales&lt;br /&gt;GROUP BY YEAR(DateKey)&lt;br /&gt;ORDER BY YEAR(DateKey)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_17.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Sin embargo, nuestro objetivo consiste en efectuar la suma de &amp;#39;FactSales&amp;#39;[SalesAmount] para cada combinaci&amp;oacute;n de &amp;#39;DimGeography&amp;#39;[ContinentName], &amp;#39;DimStore&amp;#39;[StoreType], &amp;#39;DimProduct&amp;#39;[BrandName] y &amp;#39;DimDate&amp;#39;[CalendarYear]. Supongamos que tuvi&amp;eacute;ramos que construir esta consulta para ejecutarla en el motor relacional. La sentencia SQL a emplear, utilizando CTEs, ser&amp;iacute;a parecida a la siguiente.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;WITH&lt;br /&gt;tblGeography AS&lt;br /&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT DISTINCT GeographyKey, ContinentName &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM DimGeography &lt;br /&gt;),&lt;br /&gt;tblStore AS&lt;br /&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT StoreKey, StoreType, tblGeography.ContinentName&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM DimStore&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; INNER JOIN tblGeography&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ON DimStore.GeographyKey = tblGeography.GeographyKey&lt;br /&gt;),&lt;br /&gt;tblProduct AS&lt;br /&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT ProductKey, BrandName&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM DimProduct&lt;br /&gt;),&lt;br /&gt;tblDate AS&lt;br /&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT Datekey, CalendarYear&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM DimDate&lt;br /&gt;)&lt;br /&gt;SELECT ContinentName, StoreType, BrandName, CalendarYear, FORMAT(SUM(SalesAmount), &amp;#39;C&amp;#39;, &amp;#39;es-es&amp;#39;) AS Ventas&lt;br /&gt;FROM FactSales&lt;br /&gt;INNER JOIN tblStore&lt;br /&gt;ON FactSales.StoreKey = tblStore.StoreKey&lt;br /&gt;INNER JOIN tblProduct&lt;br /&gt;ON FactSales.ProductKey = tblProduct.ProductKey&lt;br /&gt;INNER JOIN tblDate&lt;br /&gt;ON FactSales.DateKey = tblDate.Datekey&lt;br /&gt;GROUP BY ContinentName, StoreType, BrandName, CalendarYear&lt;br /&gt;ORDER BY ContinentName, StoreType, BrandName, CalendarYear&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_18.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Para obtener un resultado equivalente en DAX debemos cambiar la posici&amp;oacute;n de las funciones CROSSJOIN y ADDCOLUMNS dentro de la consulta.&lt;/p&gt;
&lt;p&gt;Como primer par&amp;aacute;metro de ADDCOLUMNS pasaremos la llamada a CROSSJOIN, y como segundo la expresi&amp;oacute;n que crea la columna calculada que realiza la suma de &amp;#39;FactSales&amp;#39;[SalesAmount]. Adicionalmente situaremos todo este c&amp;oacute;digo dentro de la funci&amp;oacute;n FILTER, a&amp;ntilde;adiendo una condici&amp;oacute;n para quitar las filas que carezcan de importe de venta.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;FILTER(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CROSSJOIN(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimGeography&amp;#39;[ContinentName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimStore&amp;#39;[StoreType]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimDate&amp;#39;[CalendarYear])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas&amp;quot;,FORMAT(SUMX(RELATEDTABLE(FactSales), &amp;#39;FactSales&amp;#39;[SalesAmount]), &amp;quot;Currency&amp;quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LEN([Ventas]) &amp;gt; 0&lt;br /&gt;)&lt;br /&gt;ORDER BY [ContinentName], [StoreType], [BrandName], [CalendarYear]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_19.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Como alternativa a lo anterior podemos volver a usar GENERATE, pasando en el primer par&amp;aacute;metro la llamada a CROSSJOIN y en el segundo la funci&amp;oacute;n ADDCOLUMNS.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;FILTER(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GENERATE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CROSSJOIN(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimGeography&amp;#39;[ContinentName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimStore&amp;#39;[StoreType]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimDate&amp;#39;[CalendarYear]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas&amp;quot;,FORMAT(SUMX(RELATEDTABLE(FactSales), &amp;#39;FactSales&amp;#39;[SalesAmount]), &amp;quot;Currency&amp;quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LEN([Ventas]) &amp;gt; 0&lt;br /&gt;)&lt;br /&gt;ORDER BY [ContinentName], [StoreType], [BrandName], [CalendarYear]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=209032" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/BISM/default.aspx">BISM</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server+2012/default.aspx">SQL Server 2012</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Tabular+Model/default.aspx">Tabular Model</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>La función GENERATE. Profundizando en el uso de DAX como lenguaje de consulta (3)</title><link>http://geeks.ms/blogs/lmblanco/archive/2013/03/19/la-funci-243-n-generate-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-3.aspx</link><pubDate>Tue, 19 Mar 2013 20:00:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:208887</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=208887</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=208887</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2013/03/19/la-funci-243-n-generate-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-3.aspx#comments</comments><description>&lt;p&gt;En la segunda parte de esta serie ilustr&amp;aacute;bamos c&amp;oacute;mo mediante el trabajo en conjunto de VALUES m&amp;aacute;s ADDCOLUMNS, logr&amp;aacute;bamos crear consultas cuyos resultados ofrecieran al mismo tiempo la informaci&amp;oacute;n de una tabla m&amp;aacute;s una operaci&amp;oacute;n de agregado sobre otra tabla relacionada.&lt;/p&gt;
&lt;p&gt;Pero habr&amp;aacute; ocasiones en que esto no sea suficiente, siendo necesario a&amp;ntilde;adir a la consulta datos de otras tablas del modelo, para ampliar y mejorar la informaci&amp;oacute;n proporcionada al usuario.&lt;/p&gt;
&lt;p&gt;Por ejemplo, tomando como punto de partida la consulta con la funci&amp;oacute;n VALUES de la entrega anterior, supongamos que adem&amp;aacute;s de la columna BrandName, necesitamos a&amp;ntilde;adir al resultado la columna CalendarYear de la tabla DimDate y un c&amp;aacute;lculo basado en la suma de las ventas realizadas por la combinaci&amp;oacute;n de las dos columnas.&lt;/p&gt;
&lt;p&gt;Si con ADDCOLUMNS intent&amp;aacute;ramos ejecutar una consulta como la siguiente se producir&amp;iacute;a un error, ya que de los par&amp;aacute;metros admitidos por esta funci&amp;oacute;n, s&amp;oacute;lo el primero puede ser una tabla o expresi&amp;oacute;n de tabla, siendo el resto expresiones que generan columnas calculadas.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimDate&amp;#39;[CalendarYear]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas por marca y a&amp;ntilde;o&amp;quot;, CALCULATE(SUM(&amp;#39;FactSales&amp;#39;[SalesAmount])) &lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;GENERATE. Enriqueciendo el resultado mediante la combinaci&amp;oacute;n de tablas&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Para resolver este problema recurriremos a la funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/gg492196.aspx"&gt;GENERATE&lt;/a&gt;, que recibe como par&amp;aacute;metro dos tablas o expresiones de tabla, generando como resultado el producto cartesiano de ambas. A continuaci&amp;oacute;n vemos una consulta de ejemplo que emplea esta funci&amp;oacute;n para combinar las tablas DimStore y DimGeography.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;GENERATE(&amp;#39;DimStore&amp;#39;,&amp;#39;DimGeography&amp;#39;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Observando el resultado, apreciaremos ocurrencias de filas en la tabla DimStore que tienen una correspondencia geogr&amp;aacute;fica incorrecta al combinarse con la tabla DimGeography, debido precisamente al modo en el que se realiza el cruce entre los registros de ambas tablas. En breve explicaremos c&amp;oacute;mo arreglar este aspecto en particular.&lt;/p&gt;
&lt;p&gt;La forma de aplicar GENERATE para resolver nuestro problema consiste en pasarle como primer par&amp;aacute;metro la funci&amp;oacute;n VALUES, creando as&amp;iacute; la columna con las marcas de productos; y como segundo par&amp;aacute;metro la funci&amp;oacute;n ADDCOLUMNS, para crear tanto la columna de a&amp;ntilde;os como la columna calculada con la suma de ventas. Todo ello lo vemos en la siguiente consulta.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;GENERATE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimDate&amp;#39;[CalendarYear]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas por marca y a&amp;ntilde;o&amp;quot;, SUMX(RELATEDTABLE(&amp;#39;FactSales&amp;#39;), &amp;#39;FactSales&amp;#39;[SalesAmount])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br /&gt;)&lt;br /&gt;ORDER BY [BrandName], [CalendarYear]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En el conjunto de resultados obtenido, como ya hemos mencionado, habr&amp;aacute; filas con el valor de la columna &amp;quot;Ventas por marca y a&amp;ntilde;o&amp;quot; vac&amp;iacute;as, que corresponder&amp;aacute;n a registros de la tabla FactSales para los que no se han producido ventas en la fecha con la que se est&amp;aacute;n cruzando.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_11.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Para evitar la visualizaci&amp;oacute;n de las filas que no tienen valor en la columna de importe de venta agregaremos a la consulta la funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/ee634966.aspx"&gt;FILTER&lt;/a&gt;, en la que situaremos como primer par&amp;aacute;metro la expresi&amp;oacute;n anterior, mientras que en el segundo par&amp;aacute;metro escribiremos una expresi&amp;oacute;n que act&amp;uacute;e como filtro, eliminando las filas sin valor de venta.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;FILTER(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GENERATE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimDate&amp;#39;[CalendarYear]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas por marca y a&amp;ntilde;o&amp;quot;, SUMX(RELATEDTABLE(&amp;#39;FactSales&amp;#39;), &amp;#39;FactSales&amp;#39;[SalesAmount])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NOT(ISBLANK([Ventas por marca y a&amp;ntilde;o]))&lt;br /&gt;)&lt;br /&gt;ORDER BY [BrandName], [CalendarYear]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Otra variante de la expresi&amp;oacute;n de filtro podr&amp;iacute;a ser la siguiente:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;[Ventas por marca y a&amp;ntilde;o] &amp;gt; 0&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Con cualquiera de estas formas de aplicar el filtro, el conjunto de resultados ya no mostrar&amp;aacute; importes vac&amp;iacute;os.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_12.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Con Transact-SQL podemos obtener este mismo resultado utilizando una sentencia muy similar a la &amp;uacute;ltima empleada, pero a&amp;ntilde;adiendo la combinaci&amp;oacute;n con la tabla DimDate y su campo DateKey, as&amp;iacute; como el campo CalendarYear en la cl&amp;aacute;usula GROUP BY.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;WITH tblFactSales AS&lt;br /&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT DateKey, ProductKey, SalesAmount&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM FactSales&lt;br /&gt;)&lt;br /&gt;SELECT BrandName, CalendarYear, SUM(tblFactSales.SalesAmount) AS [Ventas por marca y a&amp;ntilde;o]&lt;br /&gt;FROM DimProduct&lt;br /&gt;INNER JOIN tblFactSales&lt;br /&gt;ON DimProduct.ProductKey = tblFactSales.ProductKey&lt;br /&gt;INNER JOIN DimDate&lt;br /&gt;ON DimDate.Datekey = tblFactSales.DateKey&lt;br /&gt;GROUP BY BrandName, CalendarYear&lt;br /&gt;ORDER BY BrandName, CalendarYear&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Correcci&amp;oacute;n de efectos no deseados en la ordenaci&amp;oacute;n de n&amp;uacute;meros con formato&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Si en la anterior consulta DAX aplicamos un formato (moneda, separador de millar, etc.) sobre la columna &amp;quot;Ventas por marca y a&amp;ntilde;o&amp;quot;, creada din&amp;aacute;micamente, y ordenamos por dicha columna de la siguiente manera.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;FILTER(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GENERATE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimDate&amp;#39;[CalendarYear]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas por marca y a&amp;ntilde;o&amp;quot;, FORMAT(SUMX(RELATEDTABLE(&amp;#39;FactSales&amp;#39;), &amp;#39;FactSales&amp;#39;[SalesAmount]), &amp;quot;Currency&amp;quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LEN([Ventas por marca y a&amp;ntilde;o]) &amp;gt; 0&lt;br /&gt;)&lt;br /&gt;ORDER BY [Ventas por marca y a&amp;ntilde;o]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;El resultado no se mostrar&amp;aacute; ordenado tal y como esperamos.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_13.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Esto es debido a que la columna &amp;quot;Ventas por marca y a&amp;ntilde;o&amp;quot;, por causa del formateo aplicado, contiene datos de tipo car&amp;aacute;cter en lugar de num&amp;eacute;ricos, lo que produce el aparentemente extra&amp;ntilde;o comportamiento en la ordenaci&amp;oacute;n, que en realidad no es tal, ya que se trata del modo correcto de ordenar una columna de tipo string (obs&amp;eacute;rvese tambi&amp;eacute;n que para la condici&amp;oacute;n de filtro hemos utilizado la funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/ee634917.aspx"&gt;LEN&lt;/a&gt;, que se emplea en el manejo de cadenas).&lt;/p&gt;
&lt;p&gt;Vamos a solucionar este inconveniente recurriendo de nuevo a la creaci&amp;oacute;n de medidas mediante la instrucci&amp;oacute;n DEFINE, con la que crearemos la medida que realiza la suma de las ventas, la cual emplearemos en los siguientes puntos de la consulta: dentro de ADDCOLUMNS, como expresi&amp;oacute;n de filtro, y como criterio de ordenaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;DEFINE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;MEASURE &amp;#39;FactSales&amp;#39;[Ventas] = SUMX(RELATEDTABLE(&amp;#39;FactSales&amp;#39;), &amp;#39;FactSales&amp;#39;[SalesAmount])&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;FILTER(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; GENERATE(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimDate&amp;#39;[CalendarYear]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas por marca y a&amp;ntilde;o&amp;quot;, FORMAT(&amp;#39;FactSales&amp;#39;[Ventas], &amp;quot;Currency&amp;quot;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Ventas] &amp;gt; 0&lt;br /&gt;)&lt;br /&gt;ORDER BY [Ventas] DESC&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_14.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;La obtenci&amp;oacute;n de resultados procedentes de dos tablas resulta una estupenda posibilidad de la que disponemos al escribir consultas DAX, aunque en escenarios en los que debamos manejar informaci&amp;oacute;n de un mayor n&amp;uacute;mero de tablas resultar&amp;aacute; insuficiente. En la siguiente parte de esta serie abordaremos dicha cuesti&amp;oacute;n.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=208887" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/BISM/default.aspx">BISM</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server+2012/default.aspx">SQL Server 2012</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Tabular+Model/default.aspx">Tabular Model</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>La función VALUES y la creación de medidas calculadas. Profundizando en el uso de DAX como lenguaje de consulta (2)</title><link>http://geeks.ms/blogs/lmblanco/archive/2013/03/12/la-funci-243-n-values-y-la-creaci-243-n-de-medidas-calculadas-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-2.aspx</link><pubDate>Tue, 12 Mar 2013 08:59:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:208840</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=208840</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=208840</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2013/03/12/la-funci-243-n-values-y-la-creaci-243-n-de-medidas-calculadas-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-2.aspx#comments</comments><description>&lt;p&gt;En la primera parte de esta serie comenzamos abordando la creaci&amp;oacute;n de columnas calculadas, que un&amp;iacute;amos al resto de columnas de la tabla mediante la funci&amp;oacute;n ADDCOLUMNS. En esta segunda entrega veremos c&amp;oacute;mo construir consultas basadas en los valores de una &amp;uacute;nica columna.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;VALUES. Valores distintos de una columna&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Aunque la funci&amp;oacute;n ADDCOLUMNS es adecuada para dotar de valores adicionales a una tabla, puede suceder que en determinados momentos estemos m&amp;aacute;s interesados en obtener el contenido de una sola de sus columnas, y m&amp;aacute;s concretamente, de los distintos valores que la componen, bien para visualizarlos o como parte de una expresi&amp;oacute;n m&amp;aacute;s compleja.&lt;/p&gt;
&lt;p&gt;Para tal cometido disponemos de la funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/ee634547.aspx"&gt;VALUES&lt;/a&gt;, que recibe como par&amp;aacute;metro una columna de la que extrae sus distintos valores, retorn&amp;aacute;ndolos en forma de tabla de una sola columna, como vemos en el siguiente ejemplo, donde se muestran los nombres de las marcas de productos de la tabla DimProduct.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;VALUES(&amp;#39;DimProduct&amp;#39;[BrandName])&lt;br /&gt;ORDER BY [BrandName]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_08.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En una consulta SQL disponemos de la cl&amp;aacute;usula DISTINCT, con la que obtendremos los distintos valores de uno de los campos de la tabla.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SELECT DISTINCT BrandName &lt;br /&gt;FROM DimProduct &lt;br /&gt;ORDER BY BrandName&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Puesto que el tipo de dato devuelto por VALUES es una tabla, y ADDCOLUMNS recibe un valor de este tipo en su primer par&amp;aacute;metro, podemos combinar ambas funciones para crear una consulta en la que mostremos las marcas de productos de la tabla DimProduct, y una columna calculada que sume las ventas de la tabla FactSales, obteniendo como resultado las cifras de ventas por cada marca. Recordemos que para que la operaci&amp;oacute;n de suma se lleve a cabo correctamente emplearemos las funciones CALCULATE y SUM, o la combinaci&amp;oacute;n de SUMX y RELATEDTABLE.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas por marca&amp;quot;, CALCULATE(SUM(&amp;#39;FactSales&amp;#39;[SalesAmount]))&lt;br /&gt;)&lt;br /&gt;ORDER BY [BrandName]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_09.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;La funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/ee634943.aspx"&gt;DISTINCT&lt;/a&gt; tambi&amp;eacute;n devuelve, al igual que VALUES, los valores &amp;uacute;nicos de una columna, por lo que en la mayor&amp;iacute;a de las situaciones los resultados ser&amp;aacute;n iguales utilizando indistintamente una u otra. No obstante, en algunos casos, VALUES devolver&amp;aacute; un valor vac&amp;iacute;o o elemento desconocido, cuando al combinar dos tablas no exista correspondencia entre alguno de sus miembros.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DISTINCT(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas por marca&amp;quot;, CALCULATE(SUM(&amp;#39;FactSales&amp;#39;[SalesAmount]))&lt;br /&gt;)&lt;br /&gt;ORDER BY [BrandName]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Desde Transact-SQL necesitamos en este caso emplear la cl&amp;aacute;usula GROUP BY, puesto que junto al campo BrandName vamos a usar la funci&amp;oacute;n de agregado SUM. Para la combinaci&amp;oacute;n entre las tablas DimProduct y FactSales definiremos sobre esta &amp;uacute;ltima una expresi&amp;oacute;n com&amp;uacute;n de tabla o CTE (Common Table Expression). &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;WITH tblFactSales AS&lt;br /&gt;(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT ProductKey, SalesAmount&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; FROM FactSales&lt;br /&gt;)&lt;br /&gt;SELECT BrandName, SUM(tblFactSales.SalesAmount) AS [Ventas por marca]&lt;br /&gt;FROM DimProduct&lt;br /&gt;INNER JOIN tblFactSales&lt;br /&gt;ON DimProduct.ProductKey = tblFactSales.ProductKey&lt;br /&gt;GROUP BY BrandName&lt;br /&gt;ORDER BY BrandName&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;DEFINE y MEASURE.&lt;/b&gt;&lt;b&gt; Creaci&amp;oacute;n y&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;reutilizaci&amp;oacute;n de medidas calculadas&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Si en la anterior consulta con VALUES quisi&amp;eacute;ramos adem&amp;aacute;s ordenar el resultado por la columna &amp;quot;Ventas por marca&amp;quot;, tendr&amp;iacute;amos que repetir la expresi&amp;oacute;n que contiene la operaci&amp;oacute;n de suma en la cl&amp;aacute;usula de ordenaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas por marca&amp;quot;, CALCULATE(SUM(&amp;#39;FactSales&amp;#39;[SalesAmount])) &lt;br /&gt;)&lt;br /&gt;ORDER BY CALCULATE(SUM(&amp;#39;FactSales&amp;#39;[SalesAmount]))&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Esta situaci&amp;oacute;n puede resultar bastante inc&amp;oacute;moda en el caso de consultas extensas, provocando adem&amp;aacute;s, que nuestro c&amp;oacute;digo se vuelva m&amp;aacute;s complicado de leer y mantener.&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Una forma de evitar este tipo de reiteraciones pasa por utilizar las instrucciones &lt;a href="http://technet.microsoft.com/en-us/library/gg492156.aspx"&gt;DEFINE&lt;/a&gt; y &lt;a href="http://technet.microsoft.com/en-us/library/gg492156.aspx"&gt;MEASURE&lt;/a&gt; al comienzo de la consulta, las cuales, tal y como sus nombres indican, nos permiten definir una medida calculada que podemos reutilizar tantas veces como queramos a lo largo de la consulta. Como ventaja adicional, en el ejemplo que nos ocupa, al crear la medida con DEFINE ya no ser&amp;aacute; necesario emplear la funci&amp;oacute;n CALCULATE.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;DEFINE&lt;br /&gt;MEASURE FactSales[Ventas] = SUM(&amp;#39;FactSales&amp;#39;[SalesAmount])&lt;br /&gt;&lt;br /&gt;EVALUATE&lt;br /&gt;ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VALUES(&amp;#39;DimProduct&amp;#39;[BrandName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas por marca&amp;quot;, FORMAT(FactSales[Ventas], &amp;quot;Currency&amp;quot;)&lt;br /&gt;)&lt;br /&gt;ORDER BY FactSales[Ventas] DESC&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Para mejorar la visualizaci&amp;oacute;n de los datos al crear esta nueva versi&amp;oacute;n de la consulta incluimos la funci&amp;oacute;n FORMAT, aplicando un formato de moneda a la medida/columna calculada.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_10.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;El siguiente paso consistir&amp;aacute; en construir una consulta compuesta por columnas provenientes de varias tablas, cuesti&amp;oacute;n esta que abordaremos en las pr&amp;oacute;ximas entregas.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=208840" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/BISM/default.aspx">BISM</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server+2012/default.aspx">SQL Server 2012</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Tabular+Model/default.aspx">Tabular Model</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>La función ADDCOLUMNS. Profundizando en el uso de DAX como lenguaje de consulta (1)</title><link>http://geeks.ms/blogs/lmblanco/archive/2013/03/04/la-funci-243-n-addcolumns-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-1.aspx</link><pubDate>Mon, 04 Mar 2013 19:56:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:208767</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=208767</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=208767</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2013/03/04/la-funci-243-n-addcolumns-profundizando-en-el-uso-de-dax-como-lenguaje-de-consulta-1.aspx#comments</comments><description>&lt;p&gt;Como ya explic&amp;aacute;bamos en el art&amp;iacute;culo sobre creaci&amp;oacute;n de consultas para modelos tabulares (&lt;a href="http://geeks.ms/blogs/lmblanco/archive/2012/11/06/creaci-243-n-de-consultas-para-modelos-tabulares-en-sql-server-2012-1.aspx"&gt;primera&lt;/a&gt; y &lt;a href="http://geeks.ms/blogs/lmblanco/archive/2012/11/08/creaci-243-n-de-consultas-para-modelos-tabulares-en-sql-server-2012-y-2.aspx"&gt;segunda&lt;/a&gt; parte), el lenguaje DAX puede ser utilizado para emitir consultas contra un modelo tabular, obteniendo como respuesta un conjunto de resultados, dentro de una mec&amp;aacute;nica similar a la que estamos acostumbrados a emplear cuando trabajamos con el motor relacional, es decir, mediante sentencias SQL del estilo &amp;quot;SELECT ListaDeCampos FROM Tabla&amp;quot;. Esta funcionalidad del lenguaje recibe el nombre de &lt;i&gt;Consultas DAX&lt;/i&gt; (DAX Queries), siendo la instrucci&amp;oacute;n EVALUATE la encargada de llevarla a cabo empleando sentencias del tipo &amp;quot;EVALUATE Expresi&amp;oacute;n&amp;quot;.&lt;/p&gt;
&lt;p&gt;Aunque inicialmente, las consultas DAX no estaban disponibles en el lenguaje cuando PowerPivot hizo su primera presentaci&amp;oacute;n, la llegada de SQL Server 2012, que posiciona a Business Intelligence Semantic Model (BISM) como el nuevo paradigma en el desarrollo de soluciones de inteligencia de negocio, ha supuesto una ampliaci&amp;oacute;n de las caracter&amp;iacute;sticas del lenguaje, que ahora nos va a permitir escribir consultas contra los nuevos modelos tabulares pertenecientes a BISM.&lt;/p&gt;
&lt;p&gt;Con el presente art&amp;iacute;culo iniciamos una serie en la que continuaremos la l&amp;iacute;nea de exploraci&amp;oacute;n iniciada en el art&amp;iacute;culo antes mencionado, por lo que son recomendables, al menos, unos conocimientos b&amp;aacute;sicos sobre DAX, de forma que los ejemplos que vamos a exponer puedan ser seguidos adecuadamente. Adicionalmente, en aquellos casos en que se estime oportuno, mostraremos el c&amp;oacute;digo de la consulta tanto en lenguaje DAX como en Transact-SQL, lo que nos permitir&amp;aacute; observar las diferencias entre ambos a la hora de abordar la resoluci&amp;oacute;n de un mismo problema.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;El proyecto de ejemplo&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Como base de los ejemplos que iremos desarrollando vamos a utilizar el modelo ContosoTabular, anteriormente creado &lt;a href="http://geeks.ms/blogs/lmblanco/archive/2012/11/06/creaci-243-n-de-consultas-para-modelos-tabulares-en-sql-server-2012-1.aspx"&gt;aqu&amp;iacute;&lt;/a&gt;; aunque en esta ocasi&amp;oacute;n volveremos a abrir el proyecto de dicho modelo en SQL Server Data Tools (SSDT) para a&amp;ntilde;adir la tabla DimEmployee (necesaria en alguna de las diversas pruebas a realizar), tras lo cual desplegaremos nuevamente el modelo en el servidor de an&amp;aacute;lisis de SQL Server, actualizando as&amp;iacute; los cambios realizados. A continuaci&amp;oacute;n ejecutaremos SQL Server Management Studio (SSMS) abriendo una ventana de consulta, que a partir de este momento utilizaremos para ilustrar las funciones empleadas en la construcci&amp;oacute;n de consultas DAX.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_01.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;ADDCOLUMNS. Creaci&amp;oacute;n din&amp;aacute;mica de columnas&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;La funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/gg492204.aspx"&gt;ADDCOLUMNS&lt;/a&gt; permite crear una o varias columnas calculadas a partir de una tabla o expresi&amp;oacute;n de tabla. Como primer par&amp;aacute;metro situaremos la tabla a la que se a&amp;ntilde;adir&amp;aacute; la columna(s), definiendo a continuaci&amp;oacute;n cada una de las columnas mediante una cadena para el t&amp;iacute;tulo y una expresi&amp;oacute;n DAX con la f&amp;oacute;rmula para el c&amp;aacute;lculo de la columna.&lt;/p&gt;
&lt;p&gt;En la siguiente sentencia mostramos la tabla DimStore junto a una columna calculada que duplica el n&amp;uacute;mero de empleados de cada almac&amp;eacute;n.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Empleados Duplicados&amp;quot;, [EmployeeCount] * 2&lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_02.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Para obtener el mismo resultado utilizando la instrucci&amp;oacute;n SELECT en Transact-SQL escribiremos la siguiente consulta.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SELECT *, EmployeeCount * 2 AS [Empleados Duplicados]&lt;br /&gt;FROM DimStore&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Continuando con la tabla DimStore, supongamos que de la columna OpenDate, que contiene la fecha de apertura del almac&amp;eacute;n, queremos obtener la parte correspondiente al mes como nombre. Una posibilidad, aunque no la m&amp;aacute;s &amp;oacute;ptima, como veremos enseguida, ser&amp;iacute;a utilizar la siguiente consulta, en la que combinando ADDCOLUMNS con las funciones &lt;a href="http://technet.microsoft.com/en-us/library/ee634914.aspx"&gt;MONTH&lt;/a&gt; y &lt;a href="http://technet.microsoft.com/en-us/library/gg492166.aspx"&gt;SWITCH&lt;/a&gt;, obtenemos una nueva columna con el nombre del mes correspondiente a OpenDate.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Mes Apertura&amp;quot;, SWITCH(MONTH([OpenDate]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1,&amp;quot;Enero&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2,&amp;quot;Febrero&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3,&amp;quot;Marzo&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4,&amp;quot;Abril&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5,&amp;quot;Mayo&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6,&amp;quot;Junio&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7,&amp;quot;Julio&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8,&amp;quot;Agosto&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 9,&amp;quot;Septiembre&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10,&amp;quot;Octubre&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11,&amp;quot;Noviembre&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 12,&amp;quot;Diciembre&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_03.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;La funci&amp;oacute;n MONTH devuelve el n&amp;uacute;mero del mes de la fecha pasada como par&amp;aacute;metro. Si este resultado lo pasamos a su vez como par&amp;aacute;metro a la funci&amp;oacute;n SWITCH, para cada n&amp;uacute;mero retornamos una cadena con el nombre del mes correspondiente. &lt;/p&gt;
&lt;p&gt;Pero como ya dec&amp;iacute;amos antes, existe una forma mucho m&amp;aacute;s simple de obtener el mismo resultado, consistente en utilizar la funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/ee634924.aspx"&gt;FORMAT&lt;/a&gt;, a la que pasaremos como primer par&amp;aacute;metro la columna de fecha, y como segundo la cadena con el formato que deseamos aplicar. La siguiente expresi&amp;oacute;n consigue el mismo resultado que la anterior pero con mucho menos c&amp;oacute;digo.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Mes Apertura&amp;quot;, FORMAT([OpenDate], &amp;quot;MMMM&amp;quot;)&lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En Transact-SQL tambi&amp;eacute;n disponemos de la funci&amp;oacute;n FORMAT que se utiliza como vemos a continuaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SET LANGUAGE Spanish&lt;/p&gt;
&lt;p&gt;SELECT *, FORMAT(OpenDate, &amp;#39;MMMM&amp;#39;) AS [Mes Apertura]&lt;br /&gt;FROM DimStore&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Compliquemos ahora un poco la expresi&amp;oacute;n utilizada para crear la columna calculada: supongamos que necesitamos averiguar la cantidad de a&amp;ntilde;os transcurridos desde la fecha de apertura del almac&amp;eacute;n (columna OpenDate) hasta la fecha actual, teniendo en cuenta que si existe valor en la columna CloseDate significar&amp;aacute; que el almac&amp;eacute;n ya ha sido cerrado.&lt;/p&gt;
&lt;p&gt;La expresi&amp;oacute;n de columna para resolver esta situaci&amp;oacute;n implicar&amp;aacute;, pues, el uso de las siguientes funciones: &lt;a href="http://technet.microsoft.com/en-us/library/ee634567.aspx"&gt;YEAR&lt;/a&gt;, para extraer el a&amp;ntilde;o de las columnas de fecha; &lt;a href="http://technet.microsoft.com/en-us/library/ee634891.aspx"&gt;NOW&lt;/a&gt;, para obtener la fecha actual; &lt;a href="http://technet.microsoft.com/en-us/library/ee634204.aspx"&gt;ISBLANK&lt;/a&gt;, para comprobar la existencia de valor en la columna CloseDate; e &lt;a href="http://technet.microsoft.com/en-us/library/ee634824.aspx"&gt;IF&lt;/a&gt;, para determinar la operaci&amp;oacute;n que realiza el c&amp;aacute;lculo de a&amp;ntilde;os seg&amp;uacute;n la columna CloseDate tenga o no valor.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;A&amp;ntilde;os actividad almac&amp;eacute;n&amp;quot;, IF(ISBLANK([CloseDate]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; YEAR(NOW()) - YEAR([OpenDate]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; YEAR([CloseDate]) - YEAR([OpenDate])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_04.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En SQL usaremos la funci&amp;oacute;n DATEDIFF para hallar la diferencia entre las fechas. La expresi&amp;oacute;n CASE nos servir&amp;aacute; para utilizar en el c&amp;aacute;lculo la fecha actual o la de cierre del almac&amp;eacute;n si la primera es nula.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SELECT *,&lt;br /&gt;CASE&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHEN CloseDate IS NULL THEN&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATEDIFF(year, OpenDate, GETDATE())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ELSE&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATEDIFF(year, OpenDate, CloseDate) &lt;br /&gt;END AS [A&amp;ntilde;os actividad almac&amp;eacute;n]&lt;br /&gt;FROM DimStore&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Las columnas calculadas creadas hasta el momento con la funci&amp;oacute;n ADDCOLUMNS se basan en operaciones sobre las columnas de la propia tabla DimStore, pasada como primer par&amp;aacute;metro a la funci&amp;oacute;n. No obstante, tambi&amp;eacute;n es posible generar columnas din&amp;aacute;micas que pertenezcan a otras tablas del modelo tabular con las que DimStore guarda relaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;Observando el diagrama de tablas del modelo tabular en SSDT, vemos que DimStore mantiene relaciones con las tablas FactSales, DimGeography y DimEmployee.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_05.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Es por lo tanto perfectamente posible crear una columna calculada con ADDCOLUMNS que muestre la informaci&amp;oacute;n de la columna RegionCountryName, perteneciente a la tabla DimGeography, ya que se relaciona con la tabla DimStore a trav&amp;eacute;s de la columna GeographyKey, com&amp;uacute;n en ambas tablas. Es necesario tener en cuenta que en el momento de crear la expresi&amp;oacute;n de la columna calculada debemos indicar expl&amp;iacute;citamente la existencia de dicha relaci&amp;oacute;n utilizando la funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/ee634202.aspx"&gt;RELATED&lt;/a&gt;. Esta nueva columna tendr&amp;aacute; como t&amp;iacute;tulo &amp;quot;Pa&amp;iacute;s ubicaci&amp;oacute;n&amp;quot;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Pa&amp;iacute;s ubicaci&amp;oacute;n&amp;quot;, RELATED(&amp;#39;DimGeography&amp;#39;[RegionCountryName])&lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Adem&amp;aacute;s, tal y como explic&amp;aacute;bamos al principio de este apartado, con ADDCOLUMNS podemos crear varias columnas calculadas al mismo tiempo, por lo que a&amp;ntilde;adiremos a la consulta anterior otra expresi&amp;oacute;n con el t&amp;iacute;tulo &amp;quot;Ventas almac&amp;eacute;n&amp;quot;, que realice, empleando la funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/ee634387.aspx"&gt;SUM&lt;/a&gt;, la suma de la columna SalesAmount, perteneciente a la tabla FactSales, con la que tambi&amp;eacute;n se relaciona DimStore a trav&amp;eacute;s del campo StoreKey.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Pa&amp;iacute;s ubicaci&amp;oacute;n&amp;quot;, RELATED(&amp;#39;DimGeography&amp;#39;[RegionCountryName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas almac&amp;eacute;n&amp;quot;, SUM(&amp;#39;FactSales&amp;#39;[SalesAmount])&lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_06.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Pero observando el resultado obtenido vemos que hay algo que no funciona correctamente, ya que la finalidad de la anterior consulta consiste en obtener la suma del campo SalesAmount para cada uno de los almacenes, y lo que hemos conseguido es que el valor de la columna calculada &amp;quot;Ventas almac&amp;eacute;n&amp;quot; muestre en todos los casos la suma total de SalesAmount, lo cual no es el objetivo que perseguimos.&lt;/p&gt;
&lt;p&gt;Podemos solucionar este problema de dos formas: la primera consiste en sustituir la funci&amp;oacute;n SUM por &lt;a href="http://technet.microsoft.com/en-us/library/ee634959.aspx"&gt;SUMX&lt;/a&gt;, que sobre una tabla pasada como primer par&amp;aacute;metro realiza la suma de la columna pasada en el segundo par&amp;aacute;metro. Aqu&amp;iacute; tambi&amp;eacute;n debemos indicar que existe una relaci&amp;oacute;n entre DimStore y FactSales, para lo que usaremos la funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/ee634226.aspx"&gt;RELATEDTABLE&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Pa&amp;iacute;s ubicaci&amp;oacute;n&amp;quot;, RELATED(&amp;#39;DimGeography&amp;#39;[RegionCountryName]),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas almac&amp;eacute;n&amp;quot;, SUMX(RELATEDTABLE(&amp;#39;FactSales&amp;#39;), &amp;#39;FactSales&amp;#39;[SalesAmount])&lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;De esta forma la suma ya se realizar&amp;aacute; de forma separada para cada almac&amp;eacute;n.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201303/ProfundizandoUsoDAXComoLenguajeConsulta_5F00_07.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;La otra v&amp;iacute;a de abordar la suma de las ventas por almac&amp;eacute;n consiste en utilizar la funci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/ee634825.aspx"&gt;CALCULATE&lt;/a&gt;, a la que pasaremos como par&amp;aacute;metro la operaci&amp;oacute;n de suma. CALCULATE se encargar&amp;aacute; de evaluar dicha expresi&amp;oacute;n para cada uno de los almacenes (valores distintos del campo StoreKey) existentes en la tabla DimStore, obteniendo de esta manera el resultado deseado.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE&lt;br /&gt;ADDCOLUMNS(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;#39;DimStore&amp;#39;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Pa&amp;iacute;s ubicaci&amp;oacute;n&amp;quot;, RELATED(&amp;#39;DimGeography&amp;#39;[RegionCountryName]),&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;quot;Ventas almac&amp;eacute;n&amp;quot;, CALCULATE(SUM(&amp;#39;FactSales&amp;#39;[SalesAmount]))&lt;br /&gt;)&lt;/p&gt;
&lt;p&gt;La funci&amp;oacute;n CALCULATE puede revestir cierta complejidad inicial, por lo que recomendamos visitar el siguiente &lt;a href="http://sqlblog.com/blogs/marco_russo/archive/2010/01/03/how-calculate-works-in-dax.aspx"&gt;post&lt;/a&gt; del blog de Marco Russo, en el que realiza una detallada explicaci&amp;oacute;n acerca de su funcionamiento.&lt;/p&gt;
&lt;p&gt;Para obtener este resultado con Transact-SQL usaremos una combinaci&amp;oacute;n de tipo LEFT JOIN entre las tablas DimStore y DimGeography, adem&amp;aacute;s de una subconsulta sobre la tabla FactSales, que realice la suma del campo SalesAmount con la funci&amp;oacute;n SUM.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SELECT S.*, G.RegionCountryName,&lt;br /&gt;(SELECT SUM(F.SalesAmount) FROM FactSales AS F WHERE F.StoreKey = S.StoreKey) AS [Ventas almac&amp;eacute;n]&lt;br /&gt;FROM DimStore AS S&lt;br /&gt;LEFT JOIN DimGeography AS G&lt;br /&gt;ON S.GeographyKey = G.GeographyKey&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Como hemos podido comprobar, la funci&amp;oacute;n ADDCOLUMNS resulta de gran utilidad a la hora de a&amp;ntilde;adir a nuestras consultas informaci&amp;oacute;n adicional en forma de columnas calculadas. En las siguientes entregas explicaremos diversas t&amp;eacute;cnicas y funciones del lenguaje, mediante las que conseguiremos seleccionar un subconjunto de columnas de la tabla, evitando la necesidad de obtener la totalidad de las mismas.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=208767" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/BISM/default.aspx">BISM</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server+2012/default.aspx">SQL Server 2012</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Tabular+Model/default.aspx">Tabular Model</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>Creación de consultas para modelos tabulares en SQL Server 2012 (y 2)</title><link>http://geeks.ms/blogs/lmblanco/archive/2012/11/08/creaci-243-n-de-consultas-para-modelos-tabulares-en-sql-server-2012-y-2.aspx</link><pubDate>Thu, 08 Nov 2012 18:02:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:207365</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=207365</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=207365</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2012/11/08/creaci-243-n-de-consultas-para-modelos-tabulares-en-sql-server-2012-y-2.aspx#comments</comments><description>&lt;p&gt;En la primera parte de este art&amp;iacute;culo explic&amp;aacute;bamos la forma de crear un modelo tabular en SQL Server 2012 para su posterior consulta utilizando algunas de las t&amp;eacute;cnicas que ilustraremos en esta segunda entrega.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Consultas DAX&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Todos aquellos lectores que hayan tenido la oportunidad de trabajar con &lt;a href="http://dnmplus.net/articulos/powerpivot-dax-y-excel-business-intelligence-para-todos-los-publicos.aspx"&gt;PowerPivot&lt;/a&gt; conocer&amp;aacute;n en mayor o menor medida el lenguaje DAX y la capacidad que otorga al usuario de construir, en un modelo de datos, expresiones en forma de columnas y medidas calculadas para obtener los resultados anal&amp;iacute;ticos requeridos.&lt;/p&gt;
&lt;p&gt;En lo que respecta al desarrollo de modelos tabulares, a las funcionalidades que acabamos de mencionar se suma ahora la posibilidad de escribir consultas con las que obtener conjuntos de resultados a partir de las tablas del modelo.&lt;/p&gt;
&lt;p&gt;Para ello haremos uso de la instrucci&amp;oacute;n &lt;a href="http://technet.microsoft.com/en-us/library/gg492156.aspx"&gt;EVALUATE&lt;/a&gt; que representa la pieza fundamental en la construcci&amp;oacute;n de consultas DAX contra un modelo tabular, acompa&amp;ntilde;ando a la misma el nombre de la tabla a obtener, tal y como vemos en el siguiente ejemplo.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE DimStore;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Para poder apreciar el resultado de la ejecuci&amp;oacute;n de esta sentencia iniciaremos SSMS y nos conectaremos a Analysis Server. A continuaci&amp;oacute;n haremos clic en el modelo ContosoTabular reci&amp;eacute;n desplegado en el servidor, que aparece como nodo dependiente de la instancia de Analysis Server, y seleccionaremos la opci&amp;oacute;n de men&amp;uacute; &amp;quot;File | New | Query with Current Connection&amp;quot;, que abrir&amp;aacute; una ventana de consultas MDX que en este caso utilizaremos para escribir sentencias DAX. Antes de proseguir aclararemos al lector que cuando nos encontramos trabajando con modelos tabulares, el editor de consultas de SSMS, a pesar de guardar los archivos de sentencias con la extensi&amp;oacute;n MDX, soporta tanto consultas DAX como MDX.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_13.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Si ya hemos consultado la documentaci&amp;oacute;n oficial que sobre la instrucci&amp;oacute;n EVALUATE existe, veremos que es posible ordenar el conjunto de resultados obtenido mediante la cl&amp;aacute;usula ORDER BY, de tal forma que si modificamos nuestra consulta de la manera mostrada en la siguiente sentencia, los datos aparecer&amp;aacute;n ordenados por la columna StoreManager.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE DimStore&lt;br /&gt;ORDER BY [StoreManager];&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Podemos combinar varias columnas a la hora de ordenar, as&amp;iacute; como alterar el sentido de la ordenaci&amp;oacute;n con los modificadores ASC y DESC.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE DimStore&lt;br /&gt;ORDER BY [StoreManager] ASC, [StoreKey] DESC;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_14.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Pero a&amp;uacute;n hay m&amp;aacute;s respecto a la ordenaci&amp;oacute;n, ya que usando la subcl&amp;aacute;usula START AT conseguiremos que los datos comiencen a mostrarse a partir de un determinado valor, perteneciente a la columna(s) que participa en el orden.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EVALUATE DimStore&lt;br /&gt;ORDER BY [StoreManager] START AT 75;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Dedicaremos un pr&amp;oacute;ximo art&amp;iacute;culo a profundizar en el uso de EVALUATE y el resto de instrucciones DAX especialmente desarrolladas para el trabajo con modelos tabulares.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Elementos calculados. Medidas y columnas&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;En un modelo de datos tabular, adem&amp;aacute;s de la informaci&amp;oacute;n que obtenemos de las columnas de una tabla, podemos encontrarnos con columnas y medidas calculadas que no forman parte de la estructura original de dicha tabla, sino que son producto de una expresi&amp;oacute;n/f&amp;oacute;rmula DAX. En este apartado haremos una primera aproximaci&amp;oacute;n a este tipo de elementos de un modelo.&lt;/p&gt;
&lt;p&gt;Pongamos por ejemplo que para la tabla FactSales queremos saber cu&amp;aacute;nto ha supuesto el total de ventas, por lo que tendremos que aplicar una operaci&amp;oacute;n de suma sobre la columna SalesAmount.&lt;/p&gt;
&lt;p&gt;En primer lugar nos situaremos en dicha tabla dentro del dise&amp;ntilde;ador. Como podemos comprobar, la cuadr&amp;iacute;cula de datos se divide en dos zonas: la superior, correspondiente a los propios registros de la tabla; y la inferior, reservada a las medidas calculadas, y que actualmente se encuentra vac&amp;iacute;a.&lt;/p&gt;
&lt;p&gt;Para crear la medida que sume las filas de la columna SalesAmount haremos clic en una celda vac&amp;iacute;a de la zona inferior de dicha columna, y a continuaci&amp;oacute;n escribiremos la siguiente expresi&amp;oacute;n en la barra de f&amp;oacute;rmulas del dise&amp;ntilde;ador.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;TotalVentas:=SUM([SalesAmount])&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;De esta forma obtendremos una medida con el nombre TotalVentas, que mostrar&amp;aacute; el resultado de la operaci&amp;oacute;n de suma sobre la columna.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_15.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Tambi&amp;eacute;n conseguiremos el mismo resultado mediante la opci&amp;oacute;n de men&amp;uacute; &amp;quot;Column | AutoSum | Sum&amp;quot;, con la diferencia de que el nombre de la medida (Sum of SalesAmount) ser&amp;aacute; asignado autom&amp;aacute;ticamente, no obstante, siempre podemos recurrir a la ventana de propiedades de la medida y cambiarle el nombre en su propiedad Measure Name.&lt;/p&gt;
&lt;p&gt;Pasemos seguidamente a la creaci&amp;oacute;n de una columna calculada, donde vamos a suponer que necesitamos una nueva columna para la tabla FactSales, en la que se realice una operaci&amp;oacute;n sobre la columna SalesAmount, que arroje como resultado el valor de dicha columna para la fila actual menos el 10%. Esto lo conseguiremos haciendo clic en una celda de la primera columna vac&amp;iacute;a disponible en la tabla y escribiendo la siguiente sentencia en la barra de f&amp;oacute;rmulas.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;=[SalesAmount] - ([SalesAmount] * 0,1)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A continuaci&amp;oacute;n asignaremos el nombre a esta nueva columna haciendo doble clic en su cabecera y escribiendo el valor VentasConDescuento.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_16.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Tras la creaci&amp;oacute;n de estos miembros calculados proseguiremos con otro de los modos de consulta a nuestra disposici&amp;oacute;n: las consultas MDX.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Consultas MDX&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Aunque MDX fue desarrollado como lenguaje de consulta para cubos OLAP (modelos multidimensionales), en SQL Server 2012 ha sido adaptado para poder interaccionar tambi&amp;eacute;n con modelos tabulares, de manera que cuando lo empleamos dentro de este contexto, el nombre del modelo (archivo bim del proyecto en SSDT) representa al cubo de datos, mientras que las tablas identifican a las dimensiones. Las medidas que hayamos calculado en las diferentes tablas quedar&amp;aacute;n agrupadas en un nodo aparte, funcionando como una dimensi&amp;oacute;n especial, lo que vemos al abrir el modelo en SSMS.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_17.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Para hacer una consulta MDX contra el modelo emplearemos la instrucci&amp;oacute;n SELECT, donde al&amp;nbsp; igual que si consult&amp;aacute;ramos un cubo OLAP, especificaremos, mediante la cl&amp;aacute;usula ON COLUMNS, la dimensi&amp;oacute;n que ubicaremos en el eje de las columnas, y que en este caso ser&amp;aacute; la medida TotalVentas, ya que como hemos mencionado, las medidas del modelo tambi&amp;eacute;n pueden comportarse como una dimensi&amp;oacute;n al crear la consulta.&lt;/p&gt;
&lt;p&gt;Con la cl&amp;aacute;usula ON ROWS indicamos que la dimensi&amp;oacute;n utilizada para las filas ser&amp;aacute; DimGeography, visualizando el nombre de las provincias o estados de los pa&amp;iacute;ses con la funci&amp;oacute;n Children de MDX aplicada al atributo StateProvinceName.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SELECT&lt;/p&gt;
&lt;p&gt;{[Measures].[TotalVentas]} ON COLUMNS,&lt;/p&gt;
&lt;p&gt;{[DimGeography].[StateProvinceName].Children} ON ROWS&lt;/p&gt;
&lt;p&gt;FROM [Model];&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_18.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Agregando la cl&amp;aacute;usula WHERE a la consulta podremos aplicar filtros al resultado. Por ejemplo, si queremos que las cifras de ventas se circunscriban solamente a las ventas de productos de color azul (tabla DimProduct, atributo ColorName), emplearemos la siguiente consulta.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SELECT&lt;/p&gt;
&lt;p&gt;{[Measures].[TotalVentas]} ON COLUMNS,&lt;/p&gt;
&lt;p&gt;{[DimGeography].[RegionCountryName].Children} ON ROWS&lt;/p&gt;
&lt;p&gt;FROM [Model]&lt;/p&gt;
&lt;p&gt;WHERE ([DimProduct].[ColorName].&amp;amp;[Azul]);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_19.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Podemos desplazar la medida TotalVentas a la cl&amp;aacute;usula WHERE y poner en las columnas una selecci&amp;oacute;n de los a&amp;ntilde;os en los que se realizaron las ventas. Para especificar dichos a&amp;ntilde;os como un rango, simplemente hemos de poner el primer y &amp;uacute;ltimo elemento del mismo separados por dos puntos, tal y como vemos a continuaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;SELECT&lt;/p&gt;
&lt;p&gt;{[DimDate].[CalendarYear].&amp;amp;[2007] : [DimDate].[CalendarYear].&amp;amp;[2010]} ON COLUMNS,&lt;/p&gt;
&lt;p&gt;{[DimGeography].[RegionCountryName].Children} ON ROWS&lt;/p&gt;
&lt;p&gt;FROM [Model]&lt;/p&gt;
&lt;p&gt;WHERE ([Measures].[TotalVentas]);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_20.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Excel como herramienta de consulta&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Y llegamos a Excel, el tercero de los tipos de consulta contra modelos tabulares que estamos presentando en este art&amp;iacute;culo.&lt;/p&gt;
&lt;p&gt;Cuenta como gran ventaja con una potente interfaz de usuario, lo que nos permite construir informes de gran riqueza ya que pone a nuestra&amp;nbsp; disposici&amp;oacute;n un amplio abanico de elementos visuales tales como tablas din&amp;aacute;micas, gr&amp;aacute;ficos, estilos, formatos, etc.&lt;/p&gt;
&lt;p&gt;Una vez iniciado Excel, para acceder al contenido de un modelo tabular haremos clic en la pesta&amp;ntilde;a Datos de la cinta de opciones, y a continuaci&amp;oacute;n, dentro del grupo &amp;quot;Obtener datos externos&amp;quot;, haremos clic en la opci&amp;oacute;n &amp;quot;De otras fuentes&amp;quot; seleccionando en la lista desplegable el valor &amp;quot;Desde Analysis Services&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_21.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Como resultado se abrir&amp;aacute; un asistente en el que especificaremos el servidor\instancia a la que queremos conectarnos.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_22.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En el siguiente paso seleccionaremos la base de datos que contiene el modelo tabular (ContosoTabular) junto al propio modelo, que en el asistente estar&amp;aacute; identificado como un cubo.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_23.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En el &amp;uacute;ltimo paso guardamos la informaci&amp;oacute;n de conexi&amp;oacute;n en un archivo.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_24.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Como resultado de la ejecuci&amp;oacute;n del asistente se establecer&amp;aacute; una conexi&amp;oacute;n contra el modelo tabular, y en la hoja de c&amp;aacute;lculo se crear&amp;aacute; una tabla din&amp;aacute;mica que nos servir&amp;aacute; como veh&amp;iacute;culo para presentar los datos del modelo. En el panel de campos de la tabla din&amp;aacute;mica tendremos a nuestra disposici&amp;oacute;n las tablas y medidas que hayamos definido en el modelo, que arrastraremos, bien directamente a la&lt;a name="mk2"&gt;&lt;/a&gt; tabla o a los bloques denominados Valores, Etiquetas de fila/columna y Filtro de informe, hasta componer un informe similar al que podemos ver a continuaci&amp;oacute;n, donde analizamos las ventas de productos de color azul en funci&amp;oacute;n de los a&amp;ntilde;os y el pa&amp;iacute;s en que se ha producido la venta.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_25.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Adem&amp;aacute;s podemos a&amp;ntilde;adir un gr&amp;aacute;fico sincronizado con los valores num&amp;eacute;ricos desde la opci&amp;oacute;n Gr&amp;aacute;fico din&amp;aacute;mico, perteneciente a la pesta&amp;ntilde;a Opciones de la pesta&amp;ntilde;a de nivel superior Herramientas de tabla din&amp;aacute;mica. En dicho gr&amp;aacute;fico tambi&amp;eacute;n es posible aplicar filtros al igual que desde la tabla din&amp;aacute;mica.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_26.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Y llegados a este punto damos por concluida esta introducci&amp;oacute;n dedicada a la elaboraci&amp;oacute;n de consultas contra los nuevos modelos tabulares de SQL Server 2012, espero que resulte de ayuda a todos los que quieran empezar a dar sus primeros pasos con esta interesante tecnolog&amp;iacute;a.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=207365" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/BISM/default.aspx">BISM</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server+2012/default.aspx">SQL Server 2012</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Tabular+Model/default.aspx">Tabular Model</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>Creación de consultas para modelos tabulares en SQL Server 2012 (1)</title><link>http://geeks.ms/blogs/lmblanco/archive/2012/11/06/creaci-243-n-de-consultas-para-modelos-tabulares-en-sql-server-2012-1.aspx</link><pubDate>Tue, 06 Nov 2012 19:53:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:207337</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=207337</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=207337</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2012/11/06/creaci-243-n-de-consultas-para-modelos-tabulares-en-sql-server-2012-1.aspx#comments</comments><description>&lt;p&gt;Los Servicios de An&amp;aacute;lisis de SQL Server 2012 (SQL Server Analysis Services, SSAS) han experimentado un importante cambio con la introducci&amp;oacute;n del Modelo Sem&amp;aacute;ntico de Inteligencia de Negocio (Business Intelligence Semantic Model, BISM), un nuevo paradigma en la construcci&amp;oacute;n de sistemas anal&amp;iacute;ticos, que a&amp;uacute;na el tradicional modelo multidimensional (Unified Dimensional Model, UDM), propio de los tradicionales cubos OLAP, con el novedoso &lt;a href="http://geeks.ms/blogs/lmblanco/archive/2012/09/11/sql-server-2012-analysis-services-tabular-models.aspx"&gt;modelo tabular&lt;/a&gt;, basado en un motor de datos relacional, el cual propugna una filosof&amp;iacute;a de trabajo m&amp;aacute;s simple (aunque no menos potente en cuanto al volumen de datos a manejar) que nos permita resolver determinados problemas de una forma m&amp;aacute;s sencilla y &amp;aacute;gil que la requerida habitualmente para desarrollar un modelo multidimensional.&lt;/p&gt;
&lt;p&gt;Y es en estos &amp;uacute;ltimos, los modelos de datos tabulares, sobre los que vamos a concentrar nuestra atenci&amp;oacute;n a lo largo del presente art&amp;iacute;culo, m&amp;aacute;s concretamente en la capacidad de elaborar consultas y m&amp;eacute;tricas contra dichos modelos, las cuales nos permitan recabar la informaci&amp;oacute;n necesaria acerca de su estado.&lt;/p&gt;
&lt;p&gt;Para la confecci&amp;oacute;n de estas consultas emplearemos DAX (Data Analysis eXpressions),&amp;nbsp;el&amp;nbsp;lenguaje desarrollado con el objetivo de crear expresiones anal&amp;iacute;ticas tanto para modelos de datos en PowerPivot como para modelos tabulares en BISM. Tambi&amp;eacute;n usaremos MDX para acceder a una fuente de datos tabular como si de un cubo OLAP se tratara. Finalizaremos nuestro periplo con Excel, como ejemplo de aplicaci&amp;oacute;n de usuario final dotada igualmente de la posibilidad de obtener informaci&amp;oacute;n del modelo, present&amp;aacute;ndola con la conocida potencia gr&amp;aacute;fica de esta herramienta.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Creando el modelo tabular&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Lo primero que necesitamos para poner en pr&amp;aacute;ctica lo explicado en el p&amp;aacute;rrafo anterior es un modelo de datos tabular que podamos utilizar como banco de pruebas; as&amp;iacute; que comenzaremos arrancando SQL Server Data Tools (SSDT), el entorno de desarrollo para SQL Server 2012 basado en Visual Studio, que se encuentra en el mismo grupo de programas de SQL Server, y empleando el tipo de proyecto Analysis Services Tabular Project, crearemos un nuevo proyecto con el nombre ContosoTabular que usar&amp;aacute; &lt;a href="http://www.microsoft.com/es-es/download/details.aspx?id=18279"&gt;ContosoRetailDW&lt;/a&gt; como fuente de datos.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_01.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;El siguiente paso que daremos a continuaci&amp;oacute;n consistir&amp;aacute; en la importaci&amp;oacute;n de las tablas de la base de datos ContosoRetailDW, que posteriormente utilizaremos en nuestras operaciones de an&amp;aacute;lisis contra el modelo tabular, por lo que mediante la opci&amp;oacute;n de men&amp;uacute; &amp;quot;Model | Import From Data Source&amp;quot; de SSDT, ejecutaremos el asistente de importaci&amp;oacute;n de datos Table Import Wizard, en cuyo primer paso elegiremos el tipo de origen al que deseamos conectarnos.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_02.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En el siguiente paso introduciremos el servidor e instancia de SQL Server al que nos conectaremos (en este caso EVENDIM como servidor y SQLTABULAR como instancia), as&amp;iacute; como el nombre de la base de datos desde la que importaremos las tablas. Tambi&amp;eacute;n elegiremos Autenticaci&amp;oacute;n de Windows como m&amp;eacute;todo de conexi&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_03.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A continuaci&amp;oacute;n deberemos facilitar las credenciales de conexi&amp;oacute;n que Analysis Services utilizar&amp;aacute; para conectarse a la base de datos al realizar el proceso de importaci&amp;oacute;n. En este caso emplearemos la cuenta del usuario que ha iniciado sesi&amp;oacute;n en el equipo desde el que se desea conectar, aunque tambi&amp;eacute;n podr&amp;iacute;amos haber usado la cuenta del servicio de Analysis Services, tal y como se explica en el siguiente &lt;a href="http://geeks.ms/blogs/lmblanco/archive/2012/09/04/configurar-las-credenciales-de-acceso-a-la-fuente-de-datos-en-un-modelo-tabular-de-sql-server-2012.aspx"&gt;enlace&lt;/a&gt; de este mismo blog.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_04.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Seguidamente podemos elegir el modo en que se realizar&amp;aacute; la importaci&amp;oacute;n de los datos: mediante una selecci&amp;oacute;n de las tablas/vistas de la base de datos o usando una consulta. &lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_05.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Para este ejemplo nos decantaremos por la primera opci&amp;oacute;n, seleccionando las siguientes tablas: DimStore, DimGeography, DimDate, DimProduct, DimProductSubcategory y FactSales.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_06.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Completado este paso haremos clic en el bot&amp;oacute;n Finish, que dar&amp;aacute; comienzo al proceso de importaci&amp;oacute;n, a cuyo t&amp;eacute;rmino veremos la ventana de resultados, en la que si todo ha marchado bien, observaremos el detalle de las tablas y registros importados.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_07.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Una vez terminado el proceso de importaci&amp;oacute;n, el asistente nos devolver&amp;aacute; a la ventana del dise&amp;ntilde;ador del modelo tabular, donde tendremos a nuestra disposici&amp;oacute;n las tablas reci&amp;eacute;n importadas, organizadas en diversas pesta&amp;ntilde;as.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_08.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Tambi&amp;eacute;n es posible visualizar estas tablas en forma de diagrama mediante la opci&amp;oacute;n de men&amp;uacute; &amp;quot;Model | Model View | Diagram View&amp;quot;, lo que nos permitir&amp;aacute; seleccionar la visualizaci&amp;oacute;n de sus columnas, medidas, jerarqu&amp;iacute;as, etc., as&amp;iacute; como las relaciones existentes entre estas.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_09.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Para retornar a la anterior vista del dise&amp;ntilde;ador usaremos la opci&amp;oacute;n &amp;quot;Model | Model View | Data View&amp;quot;. &amp;nbsp;Podemos conmutar entre estas dos vistas empleando los botones situados en la parte inferior derecha del dise&amp;ntilde;ador.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_10.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Despliegue del modelo&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Finalizada por el momento la etapa de desarrollo del modelo, procederemos a efectuar el despliegue del mismo en el servidor de an&amp;aacute;lisis, de modo que pueda ser consultado por aquellas aplicaciones cliente que lo requieran. Para ello seleccionaremos la opci&amp;oacute;n de men&amp;uacute; &amp;quot;Build | Deploy ContosoTabular&amp;quot; o haremos clic derecho en el icono correspondiente al proyecto en el Explorador de Soluciones, eligiendo la opci&amp;oacute;n Deploy. Ambas acciones conducir&amp;aacute;n a la ventana de despliegue, que nos ir&amp;aacute; informando acerca del progreso de la operaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_11.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Si el despliegue se realiza con &amp;eacute;xito, cerraremos su ventana de progreso y abriremos SQL Server Management Studio (SSMS), conect&amp;aacute;ndonos a Analysis Services, donde encontraremos el modelo reci&amp;eacute;n subido al servidor. Expandiendo su nodo principal veremos las tablas que lo componen.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201211/CreacionConsultasModelosTabularesSQL2012_5F00_12.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A partir de este punto podemos comenzar a enviar consultas al modelo utilizando cualquiera de los medios a nuestra disposici&amp;oacute;n: consultas DAX, consultas MDX o Excel. Todo ello ser&amp;aacute; tratado en la segunda parte de este art&amp;iacute;culo.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=207337" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/BISM/default.aspx">BISM</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server+2012/default.aspx">SQL Server 2012</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Tabular+Model/default.aspx">Tabular Model</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>PowerPivot, DAX and Excel. Business Intelligence for all audiences</title><link>http://geeks.ms/blogs/lmblanco/archive/2012/09/17/powerpivot-dax-and-excel-business-intelligence-for-all-audiences.aspx</link><pubDate>Mon, 17 Sep 2012 19:25:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:206773</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=206773</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=206773</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2012/09/17/powerpivot-dax-and-excel-business-intelligence-for-all-audiences.aspx#comments</comments><description>&lt;p&gt;(The spanish version of this article was previously published in &lt;a href="http://dnmplus.net/articulos/powerpivot-dax-y-excel-business-intelligence-para-todos-los-publicos.aspx"&gt;dNM+&lt;/a&gt;, issue 83)&lt;/p&gt;
&lt;p&gt;PowerPivot is a technology for information analysis whose peculiarity lies in the ability of working with massive amounts of data using Excel as user interface, so it becomes an attractive offer, given the popularity of this tool belonging to the Office suite. This article introduce the reader to PowerPivot as well as DAX (Data Analysis eXpressions), the analytical expression language that accompanies it, reeling off the most important features of this technology, which coupled with traditional Analysis Services and MDX (MultiDimensional eXpressions) language, make SQL Server 2012 one of the most robust and powerful solutions in the Business Intelligence arena.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;With increasing frequency, organizations must perform diverse analysis about their status in the most varied perspectives (business, financial, HR, etc.) and on an increasingly vast amount of data, for which require suitable tools to enable them to obtain a reliable and valid information of such state.&lt;/p&gt;
&lt;p&gt;As explained in this blog&amp;#39;s &lt;a href="http://geeks.ms/blogs/lmblanco/archive/2012/07/31/olap-data-cubes-in-sql-server-2008-r2-analysis-services.aspx"&gt;article&lt;/a&gt;, OLAP data cubes are one of the key elements in this data analysis ecosystem called Business Intelligence (BI).&lt;/p&gt;
&lt;p&gt;However, a BI system, as occurs in other areas such as Web applications, desktop, etc., requires a development team and time to its creation, this latter factor sometimes extends for longer than initially estimated.&lt;/p&gt;
&lt;p&gt;Given the problems posed above, we can propose as a solution to improve development tools of the information system, which accelerate its creation time, and allow handling a greater data volume, given the widespread increase of this aspect in all corporate areas.&lt;/p&gt;
&lt;p&gt;It would also be necessary to promote the development team, incorporating new players into the system development cycle, which so far have played a role of mere validators, but they can bring great value to it, given his extensive knowledge about the structure of the various data sources available within the organization.&lt;/p&gt;
&lt;p&gt;PowerPivot comes with the aim of providing solutions to the challenges posed above, covering a number of specific areas in the development of an information system based on BI.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Self-service BI&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;When we talk about self-service, usually framed this concept within the product sales activity, where a person, the client, moves to a place, the supermarket, where products are exposed, and once there the client picks up the products, all generally without requiring the intervention of any intermediary.&lt;/p&gt;
&lt;p&gt;Within the BI context we can make an analogy with the self-service model, using a concept called &lt;i&gt;self-service BI,&lt;/i&gt; which advocates that end users (advanced or other profile) of an information system can elaborate their own analysis and reports on the system contents, to meet the specific needs emerging in several company departments, without having on these situations to rely from the enterprise BI development team.&lt;/p&gt;
&lt;p&gt;As requirements are the access need by these users to those data sources that require analysis and it is also crucial that self-service BI oriented applications have a learning curve as small as possible, so users can start being productive with them almost immediately.&lt;/p&gt;
&lt;p&gt;PowerPivot meet these requirements, since being a technology built into Excel has a wide user base already working with both, the functionality of the spreadsheet and access to external data sources, thus reducing or eliminating training in the use of user interface, and focuses on learning specific features about additional support for data analysis.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Incorporating new user profiles to the development cycle&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;In addition to release development teams a significant workload, providing self-service BI tools to end users; we get as a bonus the possibility that advanced users from various departments of the organization, through the use of such tools, to assist in the development cycle of the information system, providing ideas and suggestions.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;VertiPaq. High performance data processing engine&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;PowerPivot introduces a new data processing engine: VertiPaq, which through a column-based storage, implements a series of algorithms for data compression, by which is capable of loading millions of records in memory. &lt;/p&gt;
&lt;p&gt;However, due to the execution in memory nature of VertiPaq is recommended, whenever possible, work on a 64-bit environment, with adequate software version to this architecture: operating system, SQL Server, Office 2010, PowerPivot, etc., since it does not suffer the memory address limitations found in the 32-bit systems. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Architectural elements&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;PowerPivot, as seen in next image, consists of an assembly that is loaded into Excel process; VertiPaq engine, which handles data loading, query management and DAX expressions execution against the data warehouse, as well as PowerPivot&amp;#39;s pivot tables and charts, and finally, the OLAP provider, the Analysis Management Objects (AMO) objects and ADOMD.NET provider, allowing communication with analysis services, for gathering information from data cubes if applicable.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_01.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Collaboration environment. PowerPivot for SharePoint&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Using PowerPivot is expected that the number of analysis models created by users grows noticeably, and it is therefore very important to have a management mechanism, with respect to the publishing and access security within the organization.&lt;/p&gt;
&lt;p&gt;This is the purpose of &lt;i&gt;PowerPivot for SharePoint,&lt;/i&gt; a plug-in extending Excel Services for SharePoint, in the above paragraphs about management and collaboration.&lt;/p&gt;
&lt;p&gt;Additionally, &lt;i&gt;PowerPivot for SharePoint&lt;/i&gt; allows users to view PowerPivot models published in the organization simply using a web browser, so you only need to install Excel and &lt;i&gt;PowerPivot for Excel&lt;/i&gt; on the machines of users who will develop analytical models using this tool.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;PowerPivot. BISM cornerstone&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;(Note: for a more accurate description of BISM than below, we recommend read in first place the SSAS Tabular Models &lt;a href="http://geeks.ms/blogs/lmblanco/archive/2012/09/11/sql-server-2012-analysis-services-tabular-models.aspx"&gt;article&lt;/a&gt; which includes updated information about this technology).&lt;/p&gt;
&lt;p&gt;SQL Server 2012 ships with a new BI model called Business Intelligence Semantic Model (BISM). This model doesn&amp;#39;t replace or displace Unified Dimensional Model (UDM), the existing BI model from SQL Server 2005 but coexist with it, complementing and enriching the SQL Server offer in BI area, allowing us to have both models to work with the one that best suits our needs.&lt;/p&gt;
&lt;p&gt;SQL Server has been traditionally blamed, referring to UDM, that its implementation in BI area has a difficult learning curve with complex concepts: cubes, dimensions, measures, etc., and that the time needed to develop a solution extends too much when it comes to creating a simple analysis system.&lt;/p&gt;
&lt;p&gt;From our point of view, this learning curve isn&amp;#39;t much more complicated than we find in other aspects of software development, although we admit that from the perspective of developers used to working with a relational data model, getting familiar with the UDM-OLAP multidimensional model to build a business analytics solution may involve some initial complexity until the developer master the concepts and features of the technology.&lt;/p&gt;
&lt;p&gt;BISM comes to solve this problem, providing a simpler way of work, distinguished by its relational philosophy supported by PowerPivot and VertiPaq. While BISM is primarily oriented to the development of self-service analytical solutions or for small teams, UDM is focused in the development of corporate BI solutions, which require more planning.&lt;/p&gt;
&lt;p&gt;BISM is a model with a distributed architecture in three layers: data access, business logic and data model.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_02.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The data access layer is responsible for connecting to data sources to load the data they contain, existing two ways to operate with them: cached or real time. In the case of cached mode, data is loaded using VertiPaq, whereas if we use the real-time mode, this task is left to the original data source from which data are extracted.&lt;/p&gt;
&lt;p&gt;The business logic layer will implement the managing and processing of data that allow us to make them relevant information. We will use for this any expression languages ​​at our disposal: DAX or MDX.&lt;/p&gt;
&lt;p&gt;DAX is the expression language for data analysis built-in PowerPivot. We&amp;#39;ll use it to build queries against the data store located in VertiPaq, while MDX is the language usually employed in UDM to query OLAP cubes.&lt;/p&gt;
&lt;p&gt;DAX is not as powerful as MDX, but it is much easier to use, and aims to query data located in a self-service BI model, which theoretically should not require the use of complex queries, reserved to be made against the corporate BI system, which under normal conditions will have been developed by UDM.&lt;/p&gt;
&lt;p&gt;Finally, the data model layer will be used by client applications (Excel, SharePoint, Reporting Services, etc.) gathering information from the proper model: relational or multidimensional. Among the reporting tools that use this model is Power View, a project whose objective is to provide a better user experience for data visualization and reporting against BISM based models.&lt;/p&gt;
&lt;p&gt;Some prominent voices in the BI-related technical &lt;a href="http://cwebbbi.wordpress.com/2010/11/11/pass-summit-day-2/"&gt;community&lt;/a&gt; have expressed concern about the UDM-OLAP position with the BISM arrival in SQL Server 2012, although from Analysis Services development team wanted to send a reassuring &lt;a href="http://blogs.technet.com/b/dataplatforminsider/archive/2010/11/12/analysis-services-roadmap-for-sql-server-denali-and-beyond.aspx"&gt;message&lt;/a&gt;, insisting that BISM is not a replacement for UDM but a complementary technology.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;PowerPivot in practice&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;After architectural features review made in previous paragraphs, it&amp;#39;s time to get down to working to develop a PowerPivot model, which help us to get our first impressions about the scope of this technology.&lt;/p&gt;
&lt;p&gt;First of all we need to have Office 2010 installed, and download and install PowerPivot for Excel &lt;a href="http://www.microsoft.com/en-us/download/details.aspx?id=7609"&gt;plug-in&lt;/a&gt;. In the event that our system is 32 bit, we&amp;#39;ll download the file PowerPivot_for_Excel_x86.msi, but if we work on a 64 bit we must download the file PowerPivot_for_Excel_amd64.msi. For the sake of testing, in this article we use a Windows 7 operating system virtual machine with 1.5 GB of RAM and Intel Core 2 Duo processor.&lt;/p&gt;
&lt;p&gt;Although the name of the download page referred to SQL Server 2008 R2, it is not necessary to have it installed if we are going to work with other data formats such as Access, text files, etc. However, in our case, we will use SQL Server as data engine and the database &lt;a href="http://www.microsoft.com/en-us/download/details.aspx?id=18279"&gt;ContosoRetailDW&lt;/a&gt;. Through the latter link we&amp;#39;ll download the ContosoBIdemoBAK.exe file containing the database in format backup.&lt;/p&gt;
&lt;p&gt;The reason why we use this database is that it has some tables with millions of records, allowing us to test one of the salient features of PowerPivot: the ability to handle large volumes of data.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Creating a model&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;After restoring the database we&amp;#39;ll open Excel, then clicking on the ribbon tab &lt;i&gt;PowerPivot&lt;/i&gt;. Among the options on this tab we will click &lt;i&gt;PowerPivot window,&lt;/i&gt; belonging to &lt;i&gt;Launch&lt;/i&gt; group&lt;i&gt;,&lt;/i&gt; which as its name suggests, will open the PowerPivot working window.&lt;/p&gt;
&lt;p&gt;The first task in creating the model will be to connect to a data source to import its content, so that from the &lt;i&gt;Home&lt;/i&gt; tab of the PowerPivot window, in the &lt;i&gt;Get External Data&lt;/i&gt; group, we&amp;#39;ll click &lt;i&gt;From database&lt;/i&gt; option, selecting &lt;i&gt;From SQL Server&lt;/i&gt; among the available items.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_03.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As a result will open the &lt;i&gt;Table Import Wizard,&lt;/i&gt; where we&amp;#39;ll include information to connect to the database ContosoRetailDW. In the &lt;i&gt;Select Tables and Views&lt;/i&gt; step we will check FactSales, DimDate, DimStore and DimProduct.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_04.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;After this step will begin the import process, once completed will show each of the imported tables in different tabs in PowerPivot window.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_05.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Querying the model&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The set of tables we have just import will conduct an analysis of company sales, according to data related to the sales table: dates, products, stores, etc.&lt;/p&gt;
&lt;p&gt;To do this we will click on &lt;i&gt;PivotTable &lt;/i&gt;option in &lt;i&gt;Reports&lt;/i&gt; group reports, creating a PowerPivot&amp;#39;s PivotTable with which to perform our analysis operations. This action will move the focus to Excel window, where a dialog box will ask you the coordinates to place the PivotTable in the spreadsheet. Accepting the default values the new PivotTable will be created.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_06.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;On the pivot table&amp;#39;s right side we find the &lt;i&gt;PowerPivot Field List&lt;/i&gt; panel where we select the fields to use for our analysis, either as axis labels of rows and columns, numeric values, filters, and slicers.&lt;/p&gt;
&lt;p&gt;Those readers with expertise in creating OLAP cubes will verify that querying a PowerPivot model is very similar to the query against a data cube, but without the existence of a real cube, as in the field list panel, the items in block Values ​​represent the cube measures or metrics, while the rest of the block fields, represent the dimension attributes, displayed either in rows, columns or filter the PivotTable.&lt;/p&gt;
&lt;p&gt;We will begin creating our query by checking the field SalesAmount, from FactSales table. Due this is a numeric field, it will automatically be placed as a measure in the Values block. PowerPivot will apply then an addition operation on all records in the table to which it belongs.&lt;/p&gt;
&lt;p&gt;The current state of the PivotTable does not offer, however, great analytical possibilities, since we only have total by SalesAmount field. We need to add additional elements to the query relating to the table FactSales such as DimProduct table. This table contains each product&amp;#39;s name and additional information as manufacturer, type, color, size, etc.&lt;/p&gt;
&lt;p&gt;Suppose we want to find out the number of sales by product, but instead of using his name, we need to analyze by manufacturer. What we do in this case is check the field Manufacturer, belonging to the field list of DimProduct table. This action will place the field in the &lt;i&gt;Row Labels&lt;/i&gt; block and their values in the PivotTable row axis. In this way we will know how sales have meant by each of the manufacturers.&lt;/p&gt;
&lt;p&gt;Since the SalesAmount field values are not shown formatted, as additional work we right-click any cell in this field, choosing &lt;i&gt;Number Format...&lt;/i&gt; option. In the format dialog box select type Currency with two decimal places and euro symbol, being applied to all cells in this field in the pivot table.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_07.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Writing DAX expressions&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;As noted earlier, DAX is the expression language through which we&amp;#39;ll build the business logic in PowerPivot, both as PivotTable and data model.&lt;/p&gt;
&lt;p&gt;Before starting to write our first sentences in this language, we must know that without us aware of this, we have already written a DAX expression! If we right-click &lt;i&gt;Sum of SalesAmount&lt;/i&gt; in &lt;i&gt;Values&lt;/i&gt; block and select &lt;i&gt;Edit Measure...&lt;/i&gt;, a dialog box will open with the expression automatically created by PowerPivot&lt;/p&gt;
&lt;p&gt;=SUM(&amp;#39;FactSales&amp;#39;[SalesAmount])&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_08.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The creation of a DAX expression is very similar to writing a formula in Excel, since then the equal sign, write one or more functions with their corresponding parameters, forming the whole expression. In the expression currently under review, the SUM function will make a sum of SalesAmount field for all records in the table FactSales. If the table name has spaces or other special characters we enclose it in quotes, in other cases not necessary. With respect to the field name should always be enclosed in brackets.&lt;/p&gt;
&lt;p&gt;Now let&amp;#39;s approach to writing our own expressions, through two major elements PowerPivot: computed columns and measures. &lt;/p&gt;
&lt;p&gt;First we will create a computed column in the table FactSales, to obtain the sales amount without discounting. To this end, in PowerPivot window we should be on the last available empty column, writing in the formula bar as follows:&lt;/p&gt;
&lt;p&gt;=FactSales[UnitPrice] * FactSales[SalesQuantity]&lt;/p&gt;
&lt;p&gt;To assist in the writing of expressions, the AutoComplete feature will suggest at all times a list of functions, tables and fields, depending on what we go on writing.&lt;/p&gt;
&lt;p&gt;After writing the expression, the new column will be filled with the resulting values. Double-clicking the column header we&amp;#39;ll assign the name ImporteSinDescuento, ending the creation of computed column.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_09.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Another way to create a computed column is to click on &lt;i&gt;Add&lt;/i&gt; option from &lt;i&gt;Columns&lt;/i&gt; group, belonging to &lt;i&gt;Design&lt;/i&gt; tab.&lt;/p&gt;
&lt;p&gt;Because the fields used in the formula belong to the same table on which we are creating the calculated column, in the expression syntax we can circumvent the name of the table, being as follows:&lt;/p&gt;
&lt;p&gt;=[UnitPrice] * [SalesQuantity]&lt;/p&gt;
&lt;p&gt;To use the new column in the pivot table we&amp;#39;ll back to the Excel window, finding a warning in &lt;i&gt;PowerPivot Field List&lt;/i&gt; which informs us that data was modified. Clicking the &lt;i&gt;Refresh&lt;/i&gt; button of the warning the field list will update, adding the new field ImporteSinDescuento, which we&amp;#39;ll check to include in the PivotTable.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_10.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Our next step is creating a measure to calculate, for each manufacturer, the percentage of his sales with respect to total sales of the company.&lt;/p&gt;
&lt;p&gt;In &lt;i&gt;PowerPivot&lt;/i&gt; tab, within &lt;i&gt;Measures&lt;/i&gt; group&lt;i&gt;,&lt;/i&gt; we click the &lt;i&gt;New Measure&lt;/i&gt; option, opening the &lt;i&gt;Measure &lt;/i&gt;&lt;i&gt;Settings&lt;/i&gt; window, where we&amp;#39;ll type PorcentajeVentas as measure&amp;#39;s name and the following expression in formula field:&lt;/p&gt;
&lt;p&gt;=SUM(FactSales[SalesAmount]) / CALCULATE(SUM(FactSales[SalesAmount]), ALL(FactSales))&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_11.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The first part of this expression, as we have seen, is responsible for adding the field SalesAmount. This sum will be made for each manufacturer, because this field is used in PivotTable labels row.&lt;/p&gt;
&lt;p&gt;The second part of the expression returns, for all rows, the total sum of SalesAmount field, which we accomplish combining the functions CALCULATE, SUM and ALL. CALCULATE function evaluates the expression passed as the first parameter, which is a sum of SalesAmount field, and requires that the sum is over all FactSales table records by using the ALL function, regardless of the filters that are applied in the PivotTable.&lt;/p&gt;
&lt;p&gt;Finally, add the new measure to the pivot table by applying the percentage format.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_12.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Filters and slicers&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Our PivotTable now shows arranged by product manufacturers, a series of measures obtained from fields and calculations of FactSales table belonging to PowerPivot data model.&lt;/p&gt;
&lt;p&gt;The results of these measurements are made from all records of that table, but at some point we may also be interested to have the ability to apply filters on the model&amp;#39;s information, in order to obtain different perspectives of analysis.&lt;/p&gt;
&lt;p&gt;PowerPivot pivot tables provide the user with filters and slicers as data filtering tools. Next, we&amp;#39;ll explain to the reader to use them as a means to narrow the results of the report.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s suppose we want to filter information in the pivot table depending on the type of store where are the products. We get this data from field StoreType in DimStore table.&lt;/p&gt;
&lt;p&gt;To create a filter of this type, in the field list pane we&amp;#39;ll open out the field list of table DimStore and drag the StoreType field to the &lt;i&gt;Report Filter&lt;/i&gt; block&lt;i&gt;. &lt;/i&gt;As a result this filter is inserted in the top of the pivot table.&lt;/p&gt;
&lt;p&gt;By clicking on the filter selecting values button, we&amp;#39;ll select &amp;quot;Almac&amp;eacute;n&amp;quot;. This action will activate the filter, causing all numeric cells in the pivot table refreshing sales information depending on the filter set.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_13.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Slicers, moreover, they behave as filters, although its handling by the user is slightly different.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s create a slicer that allows us to filter the results by sales year, for which we will drag the CalendarYear field from DimDate table and drop in &lt;i&gt;Slicers Horizontal&lt;/i&gt; block. This action will create the slicer with all filter values placed above the pivot table.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_14.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Slicer values ​​that appear in a darker color tone are those with which we can make effective filters, while the use of those with a lighter shade will not produce results as there are no sales in those years.&lt;/p&gt;
&lt;p&gt;If we want to use more than one value in the slicer, we must keep down the CTRL key while clicking on the different values. The result of the filter is not effective until we release the CTRL key. To remove all filters from the segmentation will click the funnel-shaped icon situated at the top right.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Creating a PivotChart&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;In certain circumstances, the numerical data provided by a PivotTable it may not be sufficient to analyze the content of a PowerPivot model, so we also have pivot charts at our disposal, as an alternative in the information display.&lt;/p&gt;
&lt;p&gt;We can create a pivot chart from scratch or use an existing pivot table as chart&amp;#39;s foundation. In this case we&amp;#39;ll choose the latter method, for which, once positioned in the pivot table, we&amp;#39;ll click on &lt;i&gt;Options&lt;/i&gt; tab belonging to &lt;i&gt;PivotTable Tools &lt;/i&gt;category&lt;i&gt;,&lt;/i&gt; and then select &lt;i&gt;PivotChart&lt;/i&gt; option, located in the group &lt;i&gt;Tools. &lt;/i&gt;This opens the &lt;i&gt;Insert Chart&lt;/i&gt; dialog box, offering us a wide range of chart types to insert into the worksheet. Having made our choice, we will accept this dialog inserting the chart next to the PivotTable.&lt;/p&gt;
&lt;p&gt;From this point, both the table and chart will be synchronized, so that the modifications of filters, measures axes labels, etc. performed in one will be reflected immediately in the other. Next image shows the appearance of our report including pivot table and pivot chart.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201209/PowerPivotDAXExcelBusinessIntelligenceAllAudiences_5F00_15.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Conclusions&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;PowerPivot represents a technology with great potential to become an important part of the toolkit available for BI development with SQL Server. If we add capacity in handling large volumes of data, the power of its query expressions language, and the fact of using Excel as user interface, we obtain a product that allows users to create their own analysis models to address specific information needs. At the same time, these models can be of assistance to BI development teams in building corporate information systems.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=206773" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/BISM/default.aspx">BISM</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server+2012/default.aspx">SQL Server 2012</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>Population pyramids with PowerPivot. Chart development (and 2)</title><link>http://geeks.ms/blogs/lmblanco/archive/2012/04/01/population-pyramids-with-powerpivot-chart-development-and-2.aspx</link><pubDate>Sun, 01 Apr 2012 11:06:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:204133</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=204133</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=204133</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2012/04/01/population-pyramids-with-powerpivot-chart-development-and-2.aspx#comments</comments><description>&lt;p&gt;In the &lt;a href="http://geeks.ms/blogs/lmblanco/archive/2012/03/26/population-pyramids-with-powerpivot-preparing-the-data-1.aspx"&gt;first part&lt;/a&gt; of this article we developed a data model in PowerPivot representing population figures by age and sex. In this second installment will shape these figures on a chart shaped population pyramid.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pyramid chart. First approach&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In its current state, the pivot table already have enough information (figures by population, age and sex) to try to create a chart that represents a population pyramid, but we advance the reader that in this first approach we will not get the desired effect.&lt;/p&gt;
&lt;p&gt;Positioned in the pivot table, from the Excel ribbon, select the option &amp;quot;PivotChart&amp;quot; belonging to &amp;quot;Tools&amp;quot; group from &amp;quot;Options&amp;quot; tab, which in turn is contained in the top-level tab &amp;quot;PivotTable Tools&amp;quot;.&lt;/p&gt;
&lt;p&gt;This selection opens &amp;quot;Insert Chart&amp;quot; window, which contains all available chart types. Here we will realize that there is no specific template for creating a pyramid chart, therefore, of all bid at our disposal we choose, within &amp;quot;Bar&amp;quot; category, the &amp;quot;Clustered Bar&amp;quot; type, which as we shall see later, it will be the best adapted to the result we want achieve.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_22.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Accepting this window, the chart will be created from the PivotTable data, and as we anticipated, the result won&amp;#39;t look like the image presented in the first part of the article.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_23.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;However, the main difference lies in the orientation of the men bar population, which should be left. All other aspects are basically visual configuration issues, which explain how to solve in short.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solving the trajectory of the population bars&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Focusing on the male population&amp;nbsp;bar, the solution for achieve to draw itself in the opposite direction to the current, is to put in negative the values ​​of the cells in the pivot table for this segment of the population.&lt;/p&gt;
&lt;p&gt;If we were in a simple spreadsheet with no connection to PowerPivot, the solution is as simple as editing the cells in column Hombre, changing their values to negative, but in this scenario data is being obtained from the PowerPivot data model, so that it&amp;#39;s not possible directly edit the values ​​in the PivotTable.&lt;/p&gt;
&lt;p&gt;To solve this kind of problems we have to resort to the creation of columns and / or calculated measures, which through DAX expressions provide the results we need. In the transition to negative the values ​​of the Hombre column, we will open the PowerPivot window, and placing ourselves in the first available empty column in the Poblacion table, write the following expression in the formula bar:&lt;/p&gt;
&lt;p&gt;=IF([Sexo_ID] = &amp;quot;M&amp;quot;, 1, -1)&lt;/p&gt;
&lt;p&gt;We just created a calculated column that will be evaluated for each row of the Poblacion table, checking if Sexo_ID field value is equal to the letter &amp;quot;M&amp;quot; (Mujer), if so, the column value in that row will be 1, otherwise, when the field contains &amp;quot;H&amp;quot; (Hombre),&amp;nbsp;the returned value will be -1.&lt;/p&gt;
&lt;p&gt;Then we double-click its header to assign Sexo_Codigo as the column&amp;#39;s&amp;nbsp;name it. We can also give name by right clicking on the header and choosing &amp;quot;Rename Column&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_24.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Turning again to the Excel window, we&amp;#39;ll remove the chart we created in the worksheet and uncheck the RecuentoPoblacion measure, leaving empty the area of ​​the PivotTable values.&lt;/p&gt;
&lt;p&gt;The next step will be to create a new measure named SumaPoblacion, based on the following DAX expression:&lt;/p&gt;
&lt;p&gt;=SUM([Sexo_Codigo])&lt;/p&gt;
&lt;p&gt;By applying this measure to the PivotTable, the SUM function takes the sum of column values ​​passed as parameter, so the population figures of men now appear negative. This means that when re-creating the chart in the manner explained above, the indicator bars of the population values by sex are now drawn in opposite directions. As an additional feature, on &amp;quot;PivotTable Tools&amp;quot; tab, into &amp;quot;Design&amp;quot; tab, at the &amp;quot;Layout&amp;quot; group, we&amp;#39;ll drop &amp;quot;Grand Totals&amp;quot;, selecting &amp;quot;On for Columns Only&amp;quot;, that hides the row totals column, because its presence in this context is irrelevant.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_25.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Visual configuration of population bars&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Although the chart bars are now shown with the effect we wanted, it would be desirable a few tweaks in its visual appearance to improve the presentation quality.&lt;/p&gt;
&lt;p&gt;First we right click on the age ranges labels, selecting &amp;quot;Format axis&amp;quot;. In the window of the same name, under &amp;quot;Axis Options&amp;quot;, assign the value &amp;quot;Low&amp;quot; to &amp;quot;Axis Labels&amp;quot; property, which align the labels column to the left of the chart.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_26.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Then we right click on any of the bars in the graph, choosing &amp;quot;Format Data Series&amp;quot;. In the configuration series window, into &amp;quot;Series Options,&amp;quot; on property &amp;quot;Series Overlap&amp;quot; will move the position marker to the right end position (fully overlapped), while in property &amp;quot;Gap Width&amp;quot; will move the position marker to the left end (no gap at all). In this way we will accomplish the bars increase their thickness and eliminate the space between them, being completely joined to form the population pyramid.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_27.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Calculating the population percentages&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So far, the data representation obtained, both in the pivot table as in the chart pyramid is based on absolute population numbers. However, the usual practice is that such representation is made ​​as a proportion of each age group and sex on total population.&lt;/p&gt;
&lt;p&gt;For example, in our pivot table, the women population aged between 55 and 59 is 184,888 people; to get the percentage that this population group is in relation to all individuals with whom we are working (6,458,684), we divide the group by the total, and format the result as a percentage, gaining 2.86%.&lt;/p&gt;
&lt;p&gt;If we want the PivotTable to perform this operation for all population groups, we&amp;#39;ll have to add additional calculations in the form of measures, but before that we&amp;#39;ll remove the current population chart, because we will build it again from one of the new measures.&lt;/p&gt;
&lt;p&gt;We start out the existence of a measure, SumaPoblacion, which as we know, it returns the number of people adding the field Sexo_Codigo. The next step is to create a new measure, which included in the pivot table, provide the total population in all cells.&lt;/p&gt;
&lt;p&gt;Our first reaction might be to reuse the RecuentoPoblacion measure, created in the early stages of our example, but soon we realize that it is useless for this purpose, because although this measure counts the Poblacion table rows, the cells result are affected by the fields used in rows and columns, as well as other active filters in the PivotTable.&lt;/p&gt;
&lt;p&gt;For a measure always count all rows in a table, regardless of the filters may be active, we&amp;#39;ll use the CALCULATE function, which as the first parameter pass the operation to perform, in this case the count of rows in the Poblacion table using COUNTROWS function. Then pass as many parameters as filters we want to remove, using the ALL(TableName) function for each table that is, somehow, acting as a filter.&lt;/p&gt;
&lt;p&gt;Under such assumptions create a new measure called TotalGlobalPoblacion, with the following DAX expression:&lt;/p&gt;
&lt;p&gt;=CALCULATE (COUNTROWS (Poblacion), ALL (Edad), ALL (Sexo))&lt;/p&gt;
&lt;p&gt;When applied this measure to the PivotTable, all the cells show the same value: the total population.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_28.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now we need a third measure that makes the division between the two previous and display the result in percentage format. This new measure will have the name PorcentajePoblacion and use the following formula:&lt;/p&gt;
&lt;p&gt;=[SumaPoblacion] / [TotalGlobalPoblacion]&lt;/p&gt;
&lt;p&gt;As we saw in the first installment of the article, to apply the formatting to this measure will right click on one of its cells choosing &amp;quot;Number Format&amp;quot;. In the format window this time select the &amp;quot;Custom&amp;quot; category, through which we introduce in the &amp;quot;Type&amp;quot; field the following format string.&lt;/p&gt;
&lt;p&gt;0,00%;0,00%&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_29.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This string will format the number as a percentage, and show the male population columns values without the negative sign, but internally, these values ​​will remain negative.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_30.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Next deactivate all PivotTable measures except PorcentajePoblaci&amp;oacute;n, which will be the only one that remains visible. Then again add a clustered bar chart, using the configuration steps outlined above, and adding new format features to improve their presentation.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Apply percentage format to the horizontal axis &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Firstly we will right click on the horizontal axis labels by selecting &amp;quot;Format axis&amp;quot;, which will open the format window. In &amp;quot;Number&amp;quot; section, select the format category &amp;quot;Custom&amp;quot;, and in the &amp;quot;Format Code&amp;quot; field, write the following format string:&lt;/p&gt;
&lt;p&gt;0%;0%&lt;/p&gt;
&lt;p&gt;By clicking the &amp;quot;Add&amp;quot; button, the string is added to the list of custom strings. Accepting the window, the format will apply to the horizontal axis labels.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_31.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Emphasizing the population bar edges&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Then we will right click on one of the bars in the chart, choosing again &amp;quot;Format Data Series&amp;quot;. This time, in &amp;quot;Border Color&amp;quot; section, we will click &amp;quot;Solid Line&amp;quot;, selecting black color; while in &amp;quot;Border Styles&amp;quot; assign the value &amp;quot;2 pt.&amp;quot; in property &amp;quot;Width&amp;quot;. This operation will make for both groups of bars in the chart.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_32.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Then we right click on the labels of the age ranges, selecting &amp;quot;Format axis&amp;quot;. In this format window assign the same values ​​for the color and border style properties that just used to the chart bars.&lt;/p&gt;
&lt;p&gt;As a result of these actions, the chart will show the edges with an outline clearly highlighted.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_33.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Relocating the legend position&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;At the time of chart creation, Excel puts the legend (Sexo_DS field) on the right side by default. However, it is possible to change the location of this element if we want to provide more space to the drawing of population bars. To do this, we right-click the legend and select &amp;quot;Format Legend&amp;quot; in the format window, under &amp;quot;Legend Options&amp;quot;, we will click &amp;quot;Top&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_34.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As we can see, the chart has won drawing surface, but the legend indicators have been placed in reverse order with respect to the bars. To solve this problem we will click on the legend (Sexo_DS), dropping a menu of filter options, which will select &amp;quot;Sort Z to A&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_35.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;With this action, the legend indicators shall be placed properly, but now we will find that the colors of the bars have been reversed, and lost the edge of the chart bars.&lt;/p&gt;
&lt;p&gt;We will restore the edges of the bars in the manner explained above, whereas in terms of colors, for each side of the pyramid do a right click on one bar and select &amp;quot;Shape Fill&amp;quot;, changing the current color which originally had the chart.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_36.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;To complete the adjustments we are making about the legend, drag it until it is situated at the same level of the upper element of the pyramid, and will increase its width, so that the indicators are further apart.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_37.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Clear the ​​fields and add title&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Then we right click on any of the fields of the chart buttons and select the option &amp;quot;Hide All Field Buttons on Chart&amp;quot;. In this way will prevent the user to apply filters on the horizontal and / or vertical pyramid axis, keeping a solid structure thus avoiding the possibility, for example, to hide age ranges either sex. However, this filter feature will still exist from the PivotTable.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_38.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Moreover, in the tab group &amp;quot;PivotChart Tools&amp;quot; we will click on &amp;quot;Layout&amp;quot;, and within the group &amp;quot;Labels&amp;quot; will click on &amp;quot;Chart Title&amp;quot;, which will drop several items where we will choose &amp;quot;Above Chart&amp;quot;, adding a text box to the chart, we will edit to give it a title. At this point we have completed the development of our pyramid.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_39.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Energizing the data pyramid data through slicers&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Although we have achieved the stated goal of creating a population pyramid, it would be interesting to enrich the information that actually offers as we do in this section.&lt;/p&gt;
&lt;p&gt;Looking at the data model in the PowerPivot window, we shall realize that we haven&amp;#39;t use health zoning information yet, so we can use these data to construct a filter that displays the pyramid based on the population concerning one or more of these health areas.&lt;/p&gt;
&lt;p&gt;PowerPivot pivot tables, in addition to traditional filter, incorporating a new filter type called &amp;quot;slicer&amp;quot;, in addition to the usual filtering functionality provides a more flexible user interface for handle the values ​​to work with.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s create one slicer on the pyramid based on zone information. To this end, on the field list panel, drag the field Zona_DS from Zona table to &amp;quot;Slicers Horizontal&amp;quot; block, resulting in a slice located above both&amp;nbsp;the pivot table and pyramid chart.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_40.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;To filter data by slicer simply have to select the name of the health area we want to use as a filter. It is also possible to filter several areas simultaneously holding down the Ctrl key while clicking the areas composing the filter (as shown in the figure below).To remove all active filters will click on the icon located in the upper right corner of the slicer.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201204/PopulationPyramidsPowerPivot2_5F00_41.JPG" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;And at this point we concluded the article, in which its two parts we have shown how to construct a population pyramid in Excel 2010, using PowerPivot as a management tool for population data. However, the power of this technology goes beyond the mere treatment of demographic information, covering its scope to any environment where we have to make an analysis with large volumes of data.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=204133" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server+2008+R2/default.aspx">SQL Server 2008 R2</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>Population pyramids with PowerPivot. Preparing the data (1)</title><link>http://geeks.ms/blogs/lmblanco/archive/2012/03/26/population-pyramids-with-powerpivot-preparing-the-data-1.aspx</link><pubDate>Mon, 26 Mar 2012 16:56:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:204029</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=204029</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=204029</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2012/03/26/population-pyramids-with-powerpivot-preparing-the-data-1.aspx#comments</comments><description>&lt;p&gt;A population pyramid is a tool that allows to analyze the status and evolution of a population based on age and sex. This is a feature in demography and statistics, but also cover areas such as health, education, business, etc. For this reason, its integration in an computing information system belonging to one of the areas just mentioned, involves a substantial enrichment in the quality of the results obtained by the users of such systems.&lt;/p&gt;
&lt;p&gt;This article will discuss the construction of population pyramids using PowerPivot, an add-on to Excel 2010 that enables access to large volume data sources and its subsequent management and analysis.&lt;/p&gt;
&lt;p&gt;As we mentioned in the article &lt;a href="http://geeks.ms/blogs/lmblanco/archive/2011/07/18/generaci-243-n-de-datos-demogr-225-ficos-desde-sql-server.aspx"&gt;Generation of demographic data from SQL Server&lt;/a&gt;, also published in this blog, our current goal (using the PiramidePoblacion database created in that article) is to construct a chart representing a population pyramid similar to what we see in the figure below.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_01.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The first part of the article is devoted to the preparation of PowerPivot data model: connection to a data source, data load and pivot table creation to analyze the population figures. The second part will devote to the construction of the chart that represents the population pyramid, starting from the data on which we worked on the first delivery.&lt;/p&gt;
&lt;p&gt;As in the previously mentioned article, I want to thank again the members of the Health and Studies Reports Service (Directorate of Health Promotion and Prevention, DG Primary Care, Health Ministry CM): Jenaro Astray Mochales, Mar&amp;iacute;a Felicitas Dominguez Berj&amp;oacute;n, Mar&amp;iacute;a Dolores Esteban Vasallo, Beatriz Elvira Rodriguez and especially to Ricard G&amp;egrave;nova Maleras, for the support and guidance received on demographic concepts necessary to be able to properly develop a population pyramid using Excel 2010 in combination with PowerPivot. Besides all this, Ricard has kindly agreed to do a great job of reviewing this article, so the gratitude goes twice.&lt;/p&gt;
&lt;p&gt;I would also like to thank to Enrique Barcel&amp;oacute; for all his great tricks about OLAP development, shared with the team, making a little easier our development work on all these business intelligence tasks.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A little theory&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;But before to jump into its creation process, we will provide some brief theoretical notes on population pyramids that allow us to better understand their main features and the information we can collect and analyze from them.&lt;/p&gt;
&lt;p&gt;In essence, a population pyramid is a double histogram that shows the distribution by age and sex of the individuals from a population, either in absolute figures or as percentage of the total population.&lt;/p&gt;
&lt;p&gt;If we are interested in obtaining more detailed information about the conceptual aspects surrounding population pyramids, &lt;a href="http://www.sergas.es/MostrarContidos_N3_T01.aspx?IdPaxina=62714"&gt;Epidat&amp;#39;s 4.0&lt;/a&gt; documentation can be useful. This is an software application developed by the &lt;a href="http://www.sergas.es/MostrarContidos_N3_T01.aspx?IdPaxina=62713"&gt;Ministry of Health of the Xunta de Galicia&lt;/a&gt; and the &lt;a href="http://new.paho.org/blogs/esp/?p=694"&gt;Pan American Health Organization&lt;/a&gt; (OPS, Washington), from whose documentation, we quoted below some of the most important points concerning the issue at hand. First start with some ideas related to the construction of the pyramid.&lt;/p&gt;
&lt;p&gt;&amp;quot;The best way to visualize the distribution by sex and age of a population is, without doubt, the population pyramid, a true icon of demography. A pyramid is a double histogram that allows, at a single glance, to draw up a clear idea not only about the general characteristics of the population (young, aged, with some imbalance by gender) but also specific features which refer to a particular event relative to the population under study.&lt;/p&gt;
&lt;p&gt;Usually the population pyramids are constructed following several conventions and rules:&lt;/p&gt;
&lt;p&gt;- To represent men at left and women at right of the central axis.&lt;/p&gt;
&lt;p&gt;- Locating ages so as to be lower, the closer are the base and vice versa.&lt;/p&gt;
&lt;p&gt;- Maintain a certain proportionality between the base and height (3 widths by 2 levels, or 4 by 3, approximately).&lt;/p&gt;
&lt;p&gt;- Respect the same scale on both sides of the central axis (to facilitate comparison between sexes).&lt;/p&gt;
&lt;p&gt;- Represent the weight of each age interval by the area of ​​each histogram bar, not by its length, which is especially important when working with mixed age groups.&lt;/p&gt;
&lt;p&gt;- Can be built with absolute values, but preferably with the proportions of each age and sex of the total population. &lt;/p&gt;
&lt;p&gt;The last point is important and differentiates the pyramid structure indicators [proportion of young and old, aging index, etc.], which are calculated separately on the total for each respective sex. In the case of the population pyramid, using the total population of both sexes gathered, as the denominator of the proportions, not only ensures the comparability of age distribution, but also by sex.&amp;quot;&lt;/p&gt;
&lt;p&gt;And we will conclude with those items relating to the pyramid&amp;#39;s interpretation.&lt;/p&gt;
&lt;p&gt;&amp;quot;A pyramid by sex and age summarizes the demographic history of a population of at least a hundred years before the reference date (the time it takes roughly one generation to move from the base to the top of the pyramid). Sometimes, the indirect effect of some demographic events is visible beyond the leap of a century (for example, the impact of the sharp decline in fertility in recent decades experienced by many populations will be appreciated, no doubt, in the pyramids of the first half of the XXII). A simple ages pyramid [age by age: 0, 1, 2, 3 ... 99, 100 ...] allows a more accurate analysis than other age groups on aggregate (five-year, ten-year) but also suffers the risk of being affected by quality problems in the records, or be vulnerable to instability of the distributions in small populations.&lt;/p&gt;
&lt;p&gt;The first perception of a pyramid allows to identify the general features of the represented population: a broad-based pyramid that narrows quickly gives an idea of ​​a young population with a high proportion of children and adolescents, adults and elderly low, resulting of high birth and death. Conversely, a pyramid with a narrow profile at the bottom and wide at the top and the middle represents a mature or aged structure. The higher the life expectancy of a population is, most often the inequality by gender is reflected at the top of the pyramid (more full on the side of women, due to their highest level of survival).&lt;/p&gt;
&lt;p&gt;The pyramid does not provide answers for itself, but conducive to the relevant questions arise. The explanations for their profile must be found in historical, social, political and economical events and tendencies that generate consequences in demographic future -that is, in fertility, mortality and migration, which are the phenomena that shape the contours and set the size of a population- and have an interpretation in terms of the triple time perspective: age, period and cohort.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Incorporating data to PowerPivot&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Thanks to VertiPaq, the PowerPivot&amp;#39;s data processing engine, we can achieve unprecedented power and speed in handling, filtering, creating expressions of business logic, and ultimately, in all the analytical operations that we perform on a data model created with this tool.&lt;/p&gt;
&lt;p&gt;The following &lt;a href="http://www.powerpivot.com/"&gt;link&lt;/a&gt; provides access to PowerPivot&amp;#39;s web site, where we can download it, and then install it on our machine, so that we can follow the examples from this article.&lt;/p&gt;
&lt;p&gt;When PowerPivot installation concludes, we will start Excel 2010, creating a new worksheet with the name PiramidePoblacion.xlsx. In the ribbon will have now a new tab with the name &amp;quot;PowerPivot&amp;quot;. Clicking on it will select &amp;nbsp;&amp;quot;PowerPivot Window &amp;quot; belonging to the &amp;quot;Launch&amp;quot; group, which opens the aforementioned PowerPivot window, where define the table structure we will use, or &amp;quot;data model&amp;quot; as referred in PowerPivot development context.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_02.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Then in PowerPivot&amp;#39;s window &amp;quot;Home&amp;quot; tab, we&amp;#39;ll connect to the database using &amp;quot;From Database | From SQL Server&amp;quot; option, from &amp;quot;Get External Data&amp;quot; group.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_03.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This will start the &amp;quot;Table Import Wizard&amp;quot;, where indicate the data source we want to connect.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_04.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A valid data source to develop a population pyramid must have at least information about sex and age of the population, as is the case in PiramidePoblacion database. Additionally, as a way to enrich the analysis to be performed, the database may have additional information as may be the health zoning, population nationality and so on.&lt;/p&gt;
&lt;p&gt;After selecting the PiramidePoblacion database, the next step will provide a list of tables and views that we could import, of which will mark the following: Edad, Poblacion, Sexo y Zona, beginning the import by clicking on &amp;quot;Finish&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_05.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If the import process runs correctly, the wizard will display a summary of the process window.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_06.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;After the data entry concludes, we will click &amp;quot;Close&amp;quot; to return to the PowerPivot window, where we find the imported tables arranged in several tabs.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_07.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Analysis using PivotTable&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Before go back to the construction phase of the population pyramid, we will use a PivotTable to analyze the figures from the PowerPivot data model, so placed in its working window, we will click on &amp;quot;PivotTable&amp;quot; option, from &amp;quot;Reports&amp;quot; group.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_08.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This will position us in the Excel window, which opens a dialog where we choose the worksheet that will accomodate the PivotTable.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_09.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In our case, selecting the first option and accepting the dialog box, will create the PivotTable on a new worksheet.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_10.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;From the &amp;quot;PowerPivot Field List&amp;quot; panel we have at our disposal the fields from the data model tables, which will locate in different areas of the PivotTable (row labels, columns, values, etc.) to carry out our analysis operations. We will use for this a very similar style of work to that we would employ if we were querying an OLAP cube, since the management of the PowerPivot fields here is similar to what we can do with the dimensions and measures contained in a data cube when consulted from Excel.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s start with a simple query, consisting in a record count of the Poblacion table, grouping the information by age group, which will place in the PivotTable rows.&lt;/p&gt;
&lt;p&gt;We&amp;#39;ll make the record count through a &lt;a href="http://social.technet.microsoft.com/wiki/contents/articles/powerpivot-data-analysis-expressions-dax-language.aspx"&gt;DAX&lt;/a&gt; expression (the PowerPivot query language) located in a calculated measure, which will create by selecting &amp;quot;New Measure&amp;quot;, belonging to the &amp;quot;Measures&amp;quot; group in the &amp;quot;PowerPivot&amp;quot; tab. We&amp;#39;ll apply this measure on the Poblacion table, so we must be previously positioned on it, within the field list panel.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_11.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Selecting this option will open up the &amp;quot;Measure Settings&amp;quot; dialog, and in the formula text box we will write the following expression:&lt;/p&gt;
&lt;p&gt;=COUNTROWS(Poblacion)&lt;/p&gt;
&lt;p&gt;COUNTROWS, as its name suggests, is a function that counts the rows of the table passed as a parameter. To finish creating our measure, give it the name &amp;quot;RecuentoPoblacion&amp;quot; and click &amp;quot;OK&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_12.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Right after creating the measure, it is automatically added to Poblacion table field list and in the &amp;quot;Values&amp;quot; block, showing the table total number of rows in the pivot table.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_13.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Then select in the field list pane, the Edad_Grupo field from Edad table, which automatically placed it in the block &amp;quot;Row Labels&amp;quot;. If this is not the behavior obtained, we&amp;#39;ll manually drag the field and drop in that block.&lt;/p&gt;
&lt;p&gt;As a result of the previous action the pivot table will be updated, showing the Edad_Grupo field values in the rows axis. Regarding figures from RecuentoPoblacion measure, they should be distributed among the sections of each age, to reflect the number of records (population) corresponding for each of these sections. However, as shown in the figure below, this is is not happening, because the measure shows the same value for all rows, which is incorrect.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_14.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Relationships between tables in the model&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Observing the field panel we see that PowerPivot already noticed the problem just discussed, because on top of the panel displays a notice, which informs us that it may be necessary relationship between the tables that are being used to compose the pivot table query.&lt;/p&gt;
&lt;p&gt;This problem would not have occurred if there had been the necessary relationships between tables in the database, but as we said in the article on the creation of the database population, such relations were not created intentionally in order to demonstrate that it is also possible do it so from PowerPivot, as discussed below.&lt;/p&gt;
&lt;p&gt;To let PowerPivot automatically detect the needed connection, we will click the &amp;quot;Create&amp;quot; button next to the notice displayed on the panel fields. As a result, a window will open to create the appropriate relationship, offering additional information on it through the &amp;quot;Details&amp;quot; links.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_15.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;After relationship creation, it will be applied immediately on the pivot table without any user intervention, so it will properly display measure values ​​grouped by age.&lt;/p&gt;
&lt;p&gt;It&amp;#39;s also possible to manually create relationships between tables in the data model using the PowerPivot working window. To do this we will click the &amp;quot;Create Relationship&amp;quot; option, that belongs to the &amp;quot;Relationships&amp;quot; group, which is located in the &amp;quot;Design&amp;quot; tab of that window.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_16.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This will open a window which will select the table and column representing the source and destination of the relationship.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_17.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This way we will establish two new relationships, which have the Poblacion table as the source and Sexo and Zona tables as a destination. Additionally, using &amp;quot;Manage Relationships&amp;quot; we can see a summary of the relationships created and manage them (create, edit, delete, etc.).&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_18.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;These changes just make in the PowerPivot window may affect directly or indirectly the data we are presenting in the pivot table; for that reason, when we return to the Excel window, will see a notice on the field panel, where we click the &amp;quot;Refresh&amp;quot; button to update the data we&amp;#39;re working with.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_19.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-weight:bold;"&gt;Adding data to the column axis&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Fixed the relationships problem, now is time to add new data in the pivot table columns through Sexo_DS field from Sexo table.&lt;/p&gt;
&lt;p&gt;When selected, this field is placed by default on the &amp;quot;Row Labels&amp;quot; blocks so we&amp;#39;ll have to manually move it to &amp;quot;Column Labels&amp;quot; block, or directly drag it to the label column block.&lt;/p&gt;
&lt;p&gt;Additionally, we will format the numeric cells either by right-clicking any of them and selecting &amp;quot;Number Format&amp;quot; in the Format dialog box, where we&amp;#39;ll define it without decimal and with thousands separator.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_20.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;After these operations, the PivotTable will already display population data according to the requirements posed.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/PopulationPyramidsPowerPivot_5F00_21.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now we conclude the first part of this article. In the next installment we will reach our goal of creating a chart that represents the population pyramid using the data we have just prepared with PowerPivot.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=204029" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server+2008+R2/default.aspx">SQL Server 2008 R2</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>Superposed population pyramids with PowerPivot</title><link>http://geeks.ms/blogs/lmblanco/archive/2012/03/15/superposed-population-pyramids-with-powerpivot.aspx</link><pubDate>Thu, 15 Mar 2012 22:22:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:203847</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=203847</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=203847</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2012/03/15/superposed-population-pyramids-with-powerpivot.aspx#comments</comments><description>&lt;p&gt;In the articles that were dedicated to the creation of a population pyramid using PowerPivot ( &lt;a href="http://geeks.ms/blogs/lmblanco/archive/2012/03/26/population-pyramids-with-powerpivot-preparing-the-data-1.aspx"&gt;part1&lt;/a&gt; and &lt;a href="http://geeks.ms/blogs/lmblanco/archive/2011/08/21/pir-225-mides-de-poblaci-243-n-con-powerpivot-creaci-243-n-del-gr-225-fico-y-2.aspx"&gt;part2&lt;/a&gt; ), we saw the power that this add-on for Excel provides to users responsible for conducting information analysis on a database of demographic content.&lt;/p&gt;
&lt;p&gt;Continuing the line of work depicted in those articles, this time we will address the development of superposed population pyramids, one aspect of the work with population pyramids, which is to observe and analyze the differences by sex and age structure between two populations by direct comparison of their respective pyramids.&lt;/p&gt;
&lt;p&gt;Before proceeding I want to reiterate my thanks to Ricard G&amp;egrave;nova Maleras, a demographer specializing in population health analysis, belonging to the Reports and Studies Health Service (Directorate of Health Promotion and Prevention, DG Primary Care, Health Ministry CM) for their invaluable review work and guidance on all those concepts about creating population pyramids, which have proved so valuable in the development of this and previous articles we have published about this topic in the blog.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Brief introduction to the superposed population pyramids&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If we want to graphically describe this working scenario, firstly, we take the population pyramids to compare ...&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_01.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_01.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;... and then place a pyramid on the other, so that we can measure and analyze population differences between them, ending the operation.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_02.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_02.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If we are managing two static populations, the task is more complex than solely fill the cells in the Excel sheet with the corresponding population figures, and prepare the pyramid-shaped chart that combines the values. However, suppose we have a population base or reference, belonging to all the individuals from a region, and we want to make comparisons between this amount and a classification of the subgroups in which this population can be divided, for example, the geographic or health care areas.&lt;/p&gt;
&lt;p&gt;If the number of zones is very high, this will increase the amount of calculations and subgroups pyramids that we will need developing to compare with the main reference pyramid, increasing the complexity of demographic analysis to be performed.&lt;/p&gt;
&lt;p&gt;At this point of the problem, PowerPivot enters the arena, because if we use to manage population data we must work with, greatly simplify the development of population pyramids and subsequent analysis phase.&lt;/p&gt;
&lt;p&gt;Taking advantage of the pyramid developed in the items listed above, and reflected in the PiramidePoblacion.xlsx file, we will use that work setting as a starting point to develop, in first place, the population pyramids of different health areas, and continue with the reference pyramid creation, that depicts the Community of Madrid population.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The zoning pyramids&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;At first glance, this task may seem the most complicated, because its purpose is to create a pyramid for each one of the health area of the population we are dealing with.&lt;/p&gt;
&lt;p&gt;Nothing is further from reality however, because if we followed the early commented articles about pyramids creation, we will have realized that we already have that work done in the PiramidePoblacion.xlsx file, created as an exercise of such of those articles, due to the use of a slicer based on the table Zona, from the PowerPivot data model.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_03.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_03.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;However, in order to reorganize the names we use in this article, we will remove the measures and pyramid chart we had originally created for the PivotTable. Also change in the window PowertPivot, the table name Poblacion to PoblacionZonas, by right-clicking on the tab for the table, and choosing the menu option &amp;quot;Rename&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_04.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_04.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Next we will create again the measures for the PoblacionZonas table with the following names and expressions in DAX language.&lt;/p&gt;
&lt;p&gt;/ / PoblacionZonasSuma&lt;/p&gt;
&lt;p&gt;= SUM ([Sexo_Codigo])&lt;/p&gt;
&lt;p&gt;/ / PoblacionZonasTotal&lt;/p&gt;
&lt;p&gt;= CALCULATE (COUNTROWS (PoblacionZonas), ALL (Edad), ALL (Sexo))&lt;/p&gt;
&lt;p&gt;/ / PoblacionZonasPorcentaje&lt;/p&gt;
&lt;p&gt;= [PoblacionZonasSuma] / [PoblacionZonasTotal]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_05.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_05.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The way to create and configure the pyramid chart for these populations will be the same as in the articles already mentioned, except the edge of the bars, which in this case be assigned the color white, with a width of 2 points between thereof. Let&amp;#39;s recall that to format the bars will right click on any of them, selecting the menu option &amp;quot;Format Data Series&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_06.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_06.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In the figure below we can see the chart with the changes just discussed (including the slicer by the field Zona_DS from Zona table), showing the pyramid from one of the available areas.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_07.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_07.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The reference population pyramid&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The next step is to add to the current chart the pyramid representing the total population, so we will place on the PowerPivot window, where we will repeat the process of adding the Poblacion table from source database to the PowerPivot data model, but this time giving the name PoblacionReferencia to the PowerPivot table, and also creating the calculated column Sexo_Codigo using the following DAX expression: &amp;quot;= IF ([Sexo_ID] =&amp;quot; M &amp;quot;, 1, -1)&amp;quot; cause we need to sum up the population according to sex of individuals.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_08.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_08.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;After this operation we will create the necessary relationships between both population tables and the rest, obtaining the result shown in the figure below.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_09.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_09.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Then return to the Excel window, where we click the &amp;quot;Refresh&amp;quot; button in the &amp;quot;PowerPivot Field List&amp;quot; window to refresh its content, and incorporate the PoblacionReferencia table that we just added to the PowerPivot window.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_10.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_10.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;With respect to the necessary measures to generate the pyramid corresponding to this reference population, the following code block shows the DAX expressions used for its creation.&lt;/p&gt;
&lt;p&gt;/ / PoblacionReferenciaSuma&lt;a name="mk1"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;CALCULATE = (SUM ([Sexo_Codigo]), ALL (Area))&lt;/p&gt;
&lt;p&gt;/ / PoblacionReferenciaTotal&lt;/p&gt;
&lt;p&gt;= CALCULATE (COUNTROWS (PoblacionReferencia), ALL (Edad), ALL (Sexo), ALL (Area))&lt;/p&gt;
&lt;p&gt;/ / PoblacionReferenciaPorcentaje&lt;/p&gt;
&lt;p&gt;= [PoblacionReferenciaSuma] / [PoblacionReferenciaTotal]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Comparing the measures from the tables PoblacionReferencia and PoblacionZonas, we find in those a significant difference in the operations involved in sum and calculate the total population, consisting in the use of the ALL function applied to the Zona table, which is passed as parameter. Into the measure PoblacionReferenciaSuma we will use, furthermore, the CALCULATE function, so that the addition operation on the reference population table is carried out correctly.&lt;/p&gt;
&lt;p&gt;The ALL function, when operating in a DAX expression used to construct a calculated measure that we use, for example, in a PivotTable, cancels those filters applied to the PivotTable, which are related to table passed as a parameter to the ALL function, and in our case, as mentioned above, affects the Zona table.&lt;/p&gt;
&lt;p&gt;To verify this behavior, that will result in the pyramid of reference at the same time, in the PowerPivot fields window, drag the PoblacionReferenciaPorcentaje field to the Values ​​pane. This will result in new columns insertion into the pivot table for the measure, and bars into the pyramid chart to represent the new population figures.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_11.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_11.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As a next step apply the percentage format to the new columns of figures from the PivotTable, and then do right click on one of the new bars from the population chart, selecting the &amp;quot;Format Data Series&amp;quot;; this action will open the window of the same name, where we modify the following properties / values.&lt;/p&gt;
&lt;p&gt;- Filling: No Fill.&lt;/p&gt;
&lt;p&gt;- Border Color: solid line, color black.&lt;/p&gt;
&lt;p&gt;- Border Styles: width of 1 point.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_12.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201203/SuperposedPopulationPyramidsPowerPivot_5F00_12.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Repeating the same operation on the other bar chart data will complete the visual configuration of the new reference population pyramid, which will stay superposed on the zone pyramid, thus achieving our goal. This result allows us to appreciate the differences between the two types of people, facilitating their analysis.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_13.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_13.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;At this point we conclude this article about construction of population pyramids superposed using PowerPivot as a tool to model our data. In a future article will discuss the development of accumulated pyramids, a variety of population pyramid in which the pyramid bars provide more information, because they allow the inclusion of an additional category of classification.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=203847" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>Pirámides de población superpuestas con PowerPivot</title><link>http://geeks.ms/blogs/lmblanco/archive/2012/01/19/pir-225-mides-de-poblaci-243-n-superpuestas-con-powerpivot.aspx</link><pubDate>Thu, 19 Jan 2012 22:20:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:202891</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=202891</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=202891</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2012/01/19/pir-225-mides-de-poblaci-243-n-superpuestas-con-powerpivot.aspx#comments</comments><description>&lt;p&gt;En los art&amp;iacute;culos que dedic&amp;aacute;bamos a la creaci&amp;oacute;n de una pir&amp;aacute;mide de poblaci&amp;oacute;n empleando PowerPivot (&lt;a href="http://geeks.ms/blogs/lmblanco/archive/2011/08/18/pir-225-mides-de-poblaci-243-n-con-powerpivot-preparaci-243-n-del-entorno-de-datos-1.aspx"&gt;parte1&lt;/a&gt; y &lt;a href="http://geeks.ms/blogs/lmblanco/archive/2011/08/21/pir-225-mides-de-poblaci-243-n-con-powerpivot-creaci-243-n-del-gr-225-fico-y-2.aspx"&gt;parte2&lt;/a&gt;), pudimos comprobar la potencia que este complemento para Excel proporciona a aquellos usuarios encargados de realizar determinados an&amp;aacute;lisis de informaci&amp;oacute;n sobre una base de datos de contenido demogr&amp;aacute;fico.&lt;/p&gt;
&lt;p&gt;Continuando la l&amp;iacute;nea de trabajo abierta en aquellos art&amp;iacute;culos, en esta ocasi&amp;oacute;n abordaremos el desarrollo de pir&amp;aacute;mides de poblaci&amp;oacute;n superpuestas, un aspecto del trabajo con pir&amp;aacute;mides demogr&amp;aacute;ficas, que consiste en observar y analizar las diferencias de estructura por sexo y edad existentes entre dos poblaciones, mediante la comparaci&amp;oacute;n directa de sus respectivas pir&amp;aacute;mides.&lt;/p&gt;
&lt;p&gt;Antes de proseguir quisiera reiterar mi agradecimiento a Ricard G&amp;egrave;nova Maleras, dem&amp;oacute;grafo especializado en an&amp;aacute;lisis poblacionales sanitarios, perteneciente al Servicio de Informes de Salud y Estudios (Subdirecci&amp;oacute;n de Promoci&amp;oacute;n de la Salud y Prevenci&amp;oacute;n, DG Atenci&amp;oacute;n Primaria, Consejer&amp;iacute;a Sanidad CM), por su inestimable labor de revisi&amp;oacute;n y orientaci&amp;oacute;n en todos aquellos conceptos sobre creaci&amp;oacute;n de pir&amp;aacute;mides demogr&amp;aacute;ficas, que tan valiosos han resultado en la elaboraci&amp;oacute;n del presente y los anteriores art&amp;iacute;culos que hemos publicado acerca de este mismo tema en el blog.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Breve introducci&amp;oacute;n a las pir&amp;aacute;mides de poblaci&amp;oacute;n superpuestas&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Si queremos describir gr&amp;aacute;ficamente este escenario de trabajo, en primer lugar tomaremos las pir&amp;aacute;mides de las poblaciones a comparar...&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_01.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_01.jpg" border="0" alt="" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;...y a continuaci&amp;oacute;n colocaremos una pir&amp;aacute;mide sobre la otra, de forma que podamos apreciar y analizar las diferencias de poblaci&amp;oacute;n existentes entre ambas, finalizando as&amp;iacute; la operaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_02.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_02.jpg" border="0" alt="" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Si se trata de dos poblaciones est&amp;aacute;ticas, la tarea no reviste mayor complejidad que la de rellenar las celdas de la hoja Excel con las cifras de las poblaciones correspondientes, y preparar el gr&amp;aacute;fico con forma de pir&amp;aacute;mide que combine los valores. Sin embargo, supongamos que tenemos una poblaci&amp;oacute;n base o de referencia, perteneciente al total de individuos de una regi&amp;oacute;n, y queremos establecer comparaciones entre ese total y una clasificaci&amp;oacute;n de los subgrupos en que dicha poblaci&amp;oacute;n puede ser dividida, como por ejemplo, las zonas geogr&amp;aacute;ficas o de atenci&amp;oacute;n sanitaria.&lt;/p&gt;
&lt;p&gt;Si el n&amp;uacute;mero de zonas es muy elevado, aumentar&amp;aacute; la cantidad de c&amp;aacute;lculos y pir&amp;aacute;mides de subgrupos que necesitaremos elaborar para comparar con la pir&amp;aacute;mide principal de referencia, increment&amp;aacute;ndose la complejidad del an&amp;aacute;lisis demogr&amp;aacute;fico a realizar.&lt;/p&gt;
&lt;p&gt;Es en este punto del problema donde entra en liza PowerPivot, ya que si lo utilizamos para gestionar los datos de las poblaciones con las que debemos trabajar, simplificaremos en gran medida la elaboraci&amp;oacute;n de las pir&amp;aacute;mides de poblaci&amp;oacute;n, as&amp;iacute; como su posterior fase de an&amp;aacute;lisis.&lt;/p&gt;
&lt;p&gt;Aprovechando la pir&amp;aacute;mide desarrollada en los art&amp;iacute;culos mencionados anteriormente, y&amp;nbsp; plasmada en el archivo PiramidePoblacion.xlsx, utilizaremos dicho escenario de trabajo como punto de partida para elaborar, en primer lugar, las pir&amp;aacute;mides de poblaci&amp;oacute;n de las distintas zonas sanitarias; pasando a continuaci&amp;oacute;n a crear la pir&amp;aacute;mide de referencia, que representa a la poblaci&amp;oacute;n de la Comunidad de Madrid.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Las pir&amp;aacute;mides de zonificaci&amp;oacute;n&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;A simple vista, esta tarea puede parecer la m&amp;aacute;s complicada, debido a que el objetivo de la misma consiste en crear una pir&amp;aacute;mide por cada una de las zonas sanitarias de la poblaci&amp;oacute;n que estamos manejando.&lt;/p&gt;
&lt;p&gt;Nada m&amp;aacute;s lejos de la realidad sin embargo, puesto que si hemos seguido los art&amp;iacute;culos ya comentados sobre creaci&amp;oacute;n de pir&amp;aacute;mides, nos habremos dado cuenta de que ese trabajo ya lo tenemos hecho en el archivo PiramidePoblacion.xlsx, creado como ejercicio de ejemplo de dichos art&amp;iacute;culos, gracias al empleo de una segmentaci&amp;oacute;n basada en la tabla Zona del modelo de datos de PowerPivot.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_03.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_03.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;No obstante, con el fin de reorganizar los nombres que utilizaremos en este art&amp;iacute;culo, vamos a eliminar las medidas y el gr&amp;aacute;fico de la pir&amp;aacute;mide que inicialmente hab&amp;iacute;amos creado para la tabla din&amp;aacute;mica. Tambi&amp;eacute;n cambiaremos, en la ventana de PowertPivot, el nombre de la tabla Poblacion por PoblacionZonas, haciendo clic derecho en la pesta&amp;ntilde;a correspondiente a la tabla, y eligiendo la opci&amp;oacute;n de men&amp;uacute; &amp;quot;Cambiar nombre&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_04.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_04.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A continuaci&amp;oacute;n crearemos de nuevo las medidas de la tabla PoblacionZonas, con los siguientes nombres y expresiones en lenguaje DAX.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;// PoblacionZonasSuma&lt;/p&gt;
&lt;p&gt;=SUM([Sexo_Codigo])&lt;/p&gt;
&lt;p&gt;// PoblacionZonasTotal&lt;/p&gt;
&lt;p&gt;=CALCULATE(COUNTROWS(PoblacionZonas),ALL(Edad),ALL(Sexo))&lt;/p&gt;
&lt;p&gt;// PoblacionZonasPorcentaje&lt;/p&gt;
&lt;p&gt;=[PoblacionZonasSuma] / [PoblacionZonasTotal]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_05.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_05.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;La forma de crear y configurar el gr&amp;aacute;fico de pir&amp;aacute;mide para estas poblaciones ser&amp;aacute; la misma que en los art&amp;iacute;culos ya indicados, con la excepci&amp;oacute;n del borde de las barras, a las que en esta ocasi&amp;oacute;n asignaremos el color blanco, con un ancho de 2 puntos entre las mismas. Recordemos que para dar formato a las barras haremos clic derecho en cualquiera de ellas, seleccionando la opci&amp;oacute;n de men&amp;uacute; &amp;quot;Dar formato a serie de datos&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_06.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_06.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En la siguiente figura podemos observar el gr&amp;aacute;fico con las modificaciones que acabamos de comentar (incluyendo la segmentaci&amp;oacute;n por el campo Zona_DS de la tabla Zona), mostrando&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; la pir&amp;aacute;mide de una de las zonas disponibles.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_07.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_07.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;La pir&amp;aacute;mide de referencia&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;El siguiente paso consistir&amp;aacute; en a&amp;ntilde;adir al gr&amp;aacute;fico actual la pir&amp;aacute;mide que representar&amp;aacute; al total de la poblaci&amp;oacute;n, para lo cual nos situaremos en la ventana de PowerPivot, donde repetiremos el proceso de agregaci&amp;oacute;n de la tabla Poblacion desde la base de datos origen hasta el modelo de datos de PowerPivot; pero en esta ocasi&amp;oacute;n daremos el nombre PoblacionReferencia a la tabla en PowerPivot, creando tambi&amp;eacute;n la columna calculada Sexo_Codigo con la expresi&amp;oacute;n DAX: &amp;nbsp;&amp;quot;=IF([Sexo_ID] = &amp;quot;M&amp;quot;, 1, -1)&amp;quot;, ya que igualmente necesitaremos sumar la poblaci&amp;oacute;n en funci&amp;oacute;n del sexo de los individuos.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_08.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_08.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Tras esta operaci&amp;oacute;n crearemos las oportunas relaciones entre ambas tablas de poblaci&amp;oacute;n y el resto, quedando el resultado mostrado por la siguiente figura.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_09.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_09.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A continuaci&amp;oacute;n volveremos a la ventana de Excel, donde haremos clic en el bot&amp;oacute;n &amp;quot;Actualizar&amp;quot; de la ventana &amp;quot;Lista de campos de PowerPivot&amp;quot;, para que se refresque su contenido, y se incorpore la tabla PoblacionReferencia que acabamos de agregar a la ventana de PowerPivot.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_10.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_10.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En cuanto a las medidas necesarias para generar la pir&amp;aacute;mide correspondiente a esta poblaci&amp;oacute;n de referencia, en el siguiente bloque de c&amp;oacute;digo se muestran las expresiones DAX a utilizar para su creaci&amp;oacute;n.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;// PoblacionReferenciaSuma&lt;/p&gt;
&lt;p&gt;=CALCULATE(SUM([Sexo_Codigo]),ALL(Zona))&lt;/p&gt;
&lt;p&gt;// PoblacionReferenciaTotal&lt;/p&gt;
&lt;p&gt;=CALCULATE(COUNTROWS(PoblacionReferencia),ALL(Edad),ALL(Sexo),ALL(Zona))&lt;/p&gt;
&lt;p&gt;// PoblacionReferenciaPorcentaje&lt;/p&gt;
&lt;p&gt;=[PoblacionReferenciaSuma] / [PoblacionReferenciaTotal]&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Comparadas las medidas de la tabla PoblacionZonas y PoblacionReferencia, encontramos en estas &amp;uacute;ltimas una importante diferencia dentro de las operaciones encargadas de sumar la poblaci&amp;oacute;n y calcular su total, consistente en el uso de la funci&amp;oacute;n ALL aplicada a la tabla Zona, la cual es pasada como par&amp;aacute;metro. En la medida PoblacionReferenciaSuma utilizaremos, adem&amp;aacute;s, la funci&amp;oacute;n CALCULATE, para que la operaci&amp;oacute;n de suma sobre la tabla de poblaci&amp;oacute;n de referencia se efect&amp;uacute;e correctamente.&lt;/p&gt;
&lt;p&gt;La funci&amp;oacute;n ALL, cuando interviene en una expresi&amp;oacute;n DAX utilizada para construir una medida calculada que empleamos, por ejemplo, en una tabla din&amp;aacute;mica, anula aquellos filtros aplicados en la tabla din&amp;aacute;mica, que est&amp;eacute;n relacionados con la tabla pasada como par&amp;aacute;metro a la funci&amp;oacute;n ALL, y que en nuestro caso, como ya hemos mencionado, afecta a la tabla Zona.&lt;/p&gt;
&lt;p&gt;Para comprobar este comportamiento, que al mismo tiempo dar&amp;aacute; como resultado la pir&amp;aacute;mide de referencia, en la ventana de campos de PowerPivot arrastraremos el campo PoblacionReferenciaPorcentaje hasta el panel Valores. Esto producir&amp;aacute; la inserci&amp;oacute;n, en la tabla din&amp;aacute;mica, de nuevas columnas para dicha medida; y en el gr&amp;aacute;fico de pir&amp;aacute;mide, de barras para representar las nuevas cifras de poblaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_11.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_11.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Como siguiente paso aplicaremos el formato de porcentaje a las nuevas columnas de cifras de la tabla din&amp;aacute;mica, y a continuaci&amp;oacute;n haremos clic derecho en una de las nuevas barras de poblaci&amp;oacute;n del gr&amp;aacute;fico, seleccionando la opci&amp;oacute;n &amp;quot;Dar formato a serie de datos&amp;quot;; acci&amp;oacute;n esta que abrir&amp;aacute; la ventana del mismo nombre, donde modificaremos las siguientes propiedades/valores.&lt;/p&gt;
&lt;p&gt;--Relleno: Sin Relleno.&lt;/p&gt;
&lt;p&gt;--Color del borde: L&amp;iacute;nea s&amp;oacute;lida, color negro.&lt;/p&gt;
&lt;p&gt;--Estilos de borde: Ancho de 1 punto.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_12.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_12.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Repitiendo esta misma operaci&amp;oacute;n sobre la otra barra de datos del gr&amp;aacute;fico completaremos la configuraci&amp;oacute;n visual de la nueva pir&amp;aacute;mide de poblaci&amp;oacute;n de referencia, que quedar&amp;aacute; superpuesta a la pir&amp;aacute;mide por zonas, logrando as&amp;iacute; nuestro objetivo. Este resultado nos permitir&amp;aacute; apreciar las diferencias entre los dos tipos de poblaci&amp;oacute;n, facilitando su an&amp;aacute;lisis.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_13.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201201/PiramidesPoblacionSuperpuestasPowerPivot_5F00_13.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Llegados a este punto damos&amp;nbsp; por concluido el presente art&amp;iacute;culo sobre construcci&amp;oacute;n de pir&amp;aacute;mides de poblaci&amp;oacute;n superpuestas, empleando PowerPivot como herramienta para modelar nuestros datos. En un pr&amp;oacute;ximo art&amp;iacute;culo abordaremos el desarrollo de pir&amp;aacute;mides acumuladas, una variedad de pir&amp;aacute;mide poblacional en la que las barras de la pir&amp;aacute;mide aportan mayor informaci&amp;oacute;n, gracias a que permiten la inclusi&amp;oacute;n de una categor&amp;iacute;a adicional de clasificaci&amp;oacute;n.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=202891" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>Pirámides de población con PowerPivot. Creación del gráfico (y 2)</title><link>http://geeks.ms/blogs/lmblanco/archive/2011/08/21/pir-225-mides-de-poblaci-243-n-con-powerpivot-creaci-243-n-del-gr-225-fico-y-2.aspx</link><pubDate>Sun, 21 Aug 2011 17:58:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:199789</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=199789</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=199789</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2011/08/21/pir-225-mides-de-poblaci-243-n-con-powerpivot-creaci-243-n-del-gr-225-fico-y-2.aspx#comments</comments><description>&lt;p&gt;En la primera parte de este art&amp;iacute;culo desarroll&amp;aacute;bamos un modelo de datos en PowerPivot que representaba las cifras de una poblaci&amp;oacute;n por edad y sexo. En esta segunda entrega plasmaremos dichas cifras en un gr&amp;aacute;fico con forma de pir&amp;aacute;mide de poblaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Gr&amp;aacute;fico de pir&amp;aacute;mide. Primer acercamiento&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;En su estado actual, la tabla din&amp;aacute;mica ya tendr&amp;iacute;a la informaci&amp;oacute;n suficiente (cifras de poblaci&amp;oacute;n, edad y sexo) como para intentar crear un gr&amp;aacute;fico que represente una pir&amp;aacute;mide de poblaci&amp;oacute;n; aunque adelantamos al lector que en esta primera aproximaci&amp;oacute;n no vamos a conseguir el efecto deseado.&lt;/p&gt;
&lt;p&gt;Posicionados en la tabla din&amp;aacute;mica, dentro de la cinta de opciones de Excel seleccionaremos la opci&amp;oacute;n &amp;quot;Gr&amp;aacute;fico din&amp;aacute;mico&amp;quot;, perteneciente al grupo &amp;quot;Herramientas&amp;quot; de la ficha &amp;quot;Opciones&amp;quot;, que a su vez est&amp;aacute; contenida en la ficha de nivel superior &amp;quot;Herramientas de tabla din&amp;aacute;mica&amp;quot;.&lt;/p&gt;
&lt;p&gt;Esta selecci&amp;oacute;n abrir&amp;aacute; la ventana &amp;quot;Insertar gr&amp;aacute;fico&amp;quot;, que contiene el conjunto de tipos de gr&amp;aacute;fico disponibles. Aqu&amp;iacute; nos percataremos de que no existe una plantilla espec&amp;iacute;fica para crear un gr&amp;aacute;fico de pir&amp;aacute;mide; por lo tanto, entre toda la oferta a nuestra disposici&amp;oacute;n elegiremos, dentro de la categor&amp;iacute;a &amp;quot;Barra&amp;quot;, el tipo &amp;quot;Barra agrupada&amp;quot;, que como veremos m&amp;aacute;s adelante ser&amp;aacute; el que mejor se adaptar&amp;aacute; al resultado que queremos conseguir.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_22.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Aceptando esta ventana, el gr&amp;aacute;fico ser&amp;aacute; creado a partir de los datos de la tabla din&amp;aacute;mica, y tal y como hab&amp;iacute;amos anticipado, el resultado no se parecer&amp;aacute; a la imagen presentada al principio del art&amp;iacute;culo.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_23.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;No obstante, la principal diferencia radica en el dibujo de la barra correspondiente a la poblaci&amp;oacute;n de hombres, cuyo sentido deber&amp;iacute;a ser hacia la izquierda; el resto de aspectos son b&amp;aacute;sicamente cuestiones de configuraci&amp;oacute;n visual, que posteriormente explicaremos c&amp;oacute;mo resolver.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Solucionando la trayectoria de las barras de poblaci&amp;oacute;n&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Centr&amp;aacute;ndonos en la barra de poblaci&amp;oacute;n masculina, la soluci&amp;oacute;n para conseguir que se dibuje en direcci&amp;oacute;n opuesta a la que actualmente tiene, consiste en poner en negativo los valores de las celdas de la tabla din&amp;aacute;mica correspondientes a este segmento de la poblaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;Si nos encontr&amp;aacute;ramos en una hoja de c&amp;aacute;lculo simple, sin conexi&amp;oacute;n a PowerPivot, la soluci&amp;oacute;n ser&amp;iacute;a tan sencilla como editar las celdas de la columna Hombre, pasando sus valores a negativo, pero estamos en un escenario de trabajo en el que los datos est&amp;aacute;n siendo obtenidos desde el modelo de datos de PowerPivot, por lo que no es posible editar directamente los valores de la tabla din&amp;aacute;mica.&lt;/p&gt;
&lt;p&gt;Para solucionar esta clase de problemas tendremos que recurrir a la creaci&amp;oacute;n de columnas y/o medidas calculadas, que a trav&amp;eacute;s de expresiones DAX proporcionen los resultados que necesitamos. En el caso del paso a negativo de los valores de la columna Hombre, abriremos la ventana de PowerPivot, y situ&amp;aacute;ndonos en la primera columna vac&amp;iacute;a disponible en la tabla Poblaci&amp;oacute;n, escribiremos la siguiente expresi&amp;oacute;n en la barra de f&amp;oacute;rmulas:&lt;/p&gt;
&lt;p&gt;=IF([Sexo_ID] = &amp;quot;M&amp;quot;, 1, -1)&lt;/p&gt;
&lt;p&gt;Acabamos de crear una columna calculada que se evaluar&amp;aacute; para cada fila de la tabla Poblaci&amp;oacute;n, comprobando si el valor del campo Sexo_ID es igual a la letra &amp;quot;M&amp;quot;, en caso afirmativo, el valor de la columna en dicha fila ser&amp;aacute; 1, en caso contrario (cuando el campo contenga &amp;quot;H&amp;quot;) el valor devuelto ser&amp;aacute; -1.&lt;/p&gt;
&lt;p&gt;Seguidamente haremos doble clic sobre su cabecera para asignarle el nombre Sexo_Codigo. Tambi&amp;eacute;n podemos darle nombre haciendo clic derecho sobre la cabecera y eligiendo la opci&amp;oacute;n &amp;quot;Cambiar nombre de columna&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_24b.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Volviendo nuevamente a la ventana de Excel, eliminaremos el gr&amp;aacute;fico que hab&amp;iacute;amos creado en la hoja y desmarcaremos la medida RecuentoPoblacion, quedando vac&amp;iacute;a la zona de valores de la tabla din&amp;aacute;mica.&lt;/p&gt;
&lt;p&gt;El pr&amp;oacute;ximo paso a dar consistir&amp;aacute; en crear una nueva medida con el nombre SumaPoblacion, basada en la siguiente expresi&amp;oacute;n DAX:&lt;/p&gt;
&lt;p&gt;=SUM( [Sexo_Codigo] )&lt;/p&gt;
&lt;p&gt;Al aplicar esta medida a la tabla din&amp;aacute;mica, la funci&amp;oacute;n SUM realiza la suma de los valores de la columna pasada como par&amp;aacute;metro, por lo que las cifras de la poblaci&amp;oacute;n de hombres ya aparecer&amp;aacute;n en negativo. Esto significa que al volver a crear el gr&amp;aacute;fico en el modo antes explicado, las barras indicadoras de los valores de poblaci&amp;oacute;n por sexo se dibujar&amp;aacute;n ahora en direcciones opuestas. Como detalle adicional, en la ficha &amp;quot;Herramientas de tabla din&amp;aacute;mica&amp;quot;, dentro de la ficha &amp;quot;Dise&amp;ntilde;o&amp;quot;, en el grupo &amp;quot;Dise&amp;ntilde;o&amp;quot; desplegaremos la opci&amp;oacute;n &amp;quot;Totales generales&amp;quot;, seleccionando el valor &amp;quot;Activado s&amp;oacute;lo para columnas&amp;quot;, que ocultar&amp;aacute; la columna de totales de fila, ya que su presencia en este contexto resulta irrelevante.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_25.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Configuraci&amp;oacute;n visual de las barras de poblaci&amp;oacute;n&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Aunque las barras del gr&amp;aacute;fico ya se muestran seg&amp;uacute;n el efecto que nos hab&amp;iacute;amos propuesto como objetivo, ser&amp;iacute;a deseable que su aspecto visual recibiera algunos retoques para mejorar la calidad de su presentaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;En primer lugar haremos clic derecho sobre las etiquetas de los rangos de edad, seleccionando la opci&amp;oacute;n &amp;quot;Dar formato a eje&amp;quot;. En la ventana del mismo nombre, dentro del apartado &amp;quot;Opciones del eje&amp;quot;, asignaremos el valor &amp;quot;Bajo&amp;quot; a la propiedad &amp;quot;Etiquetas del eje&amp;quot;, lo que tendr&amp;aacute; como resultado que esta columna de etiquetas quede alineada a la izquierda del gr&amp;aacute;fico.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_26.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A continuaci&amp;oacute;n haremos clic derecho sobre cualquiera de las barras del gr&amp;aacute;fico, eligiendo la opci&amp;oacute;n &amp;quot;Dar formato a serie de datos&amp;quot;. En la ventana de configuraci&amp;oacute;n de la serie, dentro del apartado &amp;quot;Opciones de la serie&amp;quot;, en la propiedad &amp;quot;Superposici&amp;oacute;n de series&amp;quot;, desplazaremos el marcador de posici&amp;oacute;n hasta el extremo derecho (totalmente superpuesta), mientras que en la propiedad &amp;quot;Ancho del intervalo&amp;quot; desplazaremos el marcador de posici&amp;oacute;n hasta el extremo izquierdo (sin intervalo en absoluto). De esta forma conseguiremos que las barras aumenten su grosor y eliminen el espacio intermedio entre las mismas, quedando completamente unidas para formar la pir&amp;aacute;mide de poblaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_27.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Calculando la poblaci&amp;oacute;n en porcentajes&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;La representaci&amp;oacute;n de los datos obtenida hasta este momento, tanto en la tabla din&amp;aacute;mica como en el gr&amp;aacute;fico de pir&amp;aacute;mide, se basa en cifras absolutas de poblaci&amp;oacute;n. Sin embargo, lo habitual y recomendable es que dicha representaci&amp;oacute;n se realice como proporci&amp;oacute;n de cada grupo de edad y sexo sobre el total de la poblaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;Por ejemplo, en nuestra tabla din&amp;aacute;mica, la poblaci&amp;oacute;n de mujeres con edades comprendidas entre los 55 y 59 a&amp;ntilde;os es de 184.888 personas; para obtener el porcentaje que este grupo de poblaci&amp;oacute;n constituye en relaci&amp;oacute;n al total de individuos con el que estamos trabajando (6.458.684), dividiremos el grupo entre el total, y formatearemos el resultado como porcentaje, obteniendo 2,86 %.&lt;/p&gt;
&lt;p&gt;Si queremos que la tabla din&amp;aacute;mica realice esta operaci&amp;oacute;n para todos los grupos de poblaci&amp;oacute;n tendremos que a&amp;ntilde;adir c&amp;aacute;lculos adicionales en forma de medidas, pero antes de eso eliminaremos el actual gr&amp;aacute;fico de poblaci&amp;oacute;n, ya que volveremos a construirlo a partir de una de las nuevas medidas.&lt;/p&gt;
&lt;p&gt;Partimos de la existencia de una medida, SumaPoblacion, que como ya sabemos, devuelve la cifra de poblaci&amp;oacute;n sumando el campo Sexo_Codigo. El siguiente paso consistir&amp;aacute; en crear una nueva medida, que al incluirse en la tabla din&amp;aacute;mica, proporcione el total de poblaci&amp;oacute;n en todas las celdas.&lt;/p&gt;
&lt;p&gt;Nuestra primera reacci&amp;oacute;n podr&amp;iacute;a ser volver a utilizar la medida RecuentoPoblacion, creada en las fases iniciales de nuestro ejemplo, pero pronto nos daremos cuenta de que no sirve para este prop&amp;oacute;sito, ya que aunque esta medida cuenta las filas de la tabla Poblaci&amp;oacute;n, los resultados de las celdas se ven afectados por los campos utilizados en filas y columnas, as&amp;iacute; como otros filtros que pudiera tener activos la tabla din&amp;aacute;mica.&lt;/p&gt;
&lt;p&gt;Para que una medida cuente siempre todas las filas de una tabla, sin importar los filtros que pueda haber activos, utilizaremos la funci&amp;oacute;n CALCULATE, a la que pasaremos como primer par&amp;aacute;metro la operaci&amp;oacute;n a realizar, en este caso el recuento de filas de la tabla Poblaci&amp;oacute;n mediante la funci&amp;oacute;n COUNTROWS. A continuaci&amp;oacute;n pasaremos tantos par&amp;aacute;metros como filtros queramos eliminar, utilizando la funci&amp;oacute;n ALL(NombreTabla) por cada tabla que de alguna manera est&amp;eacute; actuando como filtro.&lt;/p&gt;
&lt;p&gt;Bajo tales premisas crearemos una nueva medida llamada TotalGlobalPoblacion, con la siguiente expresi&amp;oacute;n DAX:&lt;/p&gt;
&lt;p&gt;=CALCULATE(&amp;nbsp; COUNTROWS( Poblacion ), ALL( Edad), ALL( Sexo ) )&lt;/p&gt;
&lt;p&gt;Al aplicar sobre la tabla din&amp;aacute;mica esta medida, todas sus celdas mostrar&amp;aacute;n el mismo valor: el&amp;nbsp; total de la poblaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_28.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Ahora necesitamos una tercera medida que haga la divisi&amp;oacute;n entre las dos anteriores y muestre el resultado en formato porcentaje. Esta nueva medida tendr&amp;aacute; el &amp;quot;original&amp;quot; nombre de PorcentajePoblacion y utilizara la siguiente f&amp;oacute;rmula:&lt;/p&gt;
&lt;p&gt;=[SumaPoblacion] / [TotalGlobalPoblacion]&lt;/p&gt;
&lt;p&gt;Como ya vimos en la primera entrega del art&amp;iacute;culo, para aplicar el formato a esta medida haremos clic derecho en una de sus celdas eligiendo la opci&amp;oacute;n &amp;quot;Formato de n&amp;uacute;mero&amp;quot;. En la ventana de formato seleccionaremos esta vez la categor&amp;iacute;a &amp;quot;Personalizada&amp;quot;, a trav&amp;eacute;s de la cual introduciremos en el campo &amp;quot;Tipo&amp;quot; la siguiente cadena de formato propia.&lt;/p&gt;
&lt;p&gt;0,00%;0,00%&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_29.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Esta cadena, adem&amp;aacute;s de formatear el n&amp;uacute;mero como porcentaje, mostrar&amp;aacute; sin el signo negativo los valores de la columna de poblaci&amp;oacute;n masculina, aunque internamente, dichos valores seguir&amp;aacute;n siendo negativos.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_30.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A continuaci&amp;oacute;n desactivaremos todas las medidas de la tabla din&amp;aacute;mica a excepci&amp;oacute;n de PorcentajePoblaci&amp;oacute;n, que ser&amp;aacute; la &amp;uacute;nica que permanecer&amp;aacute; visible. Seguidamente volveremos a a&amp;ntilde;adir un gr&amp;aacute;fico de barras agrupadas, en el que adem&amp;aacute;s de utilizar los pasos de configuraci&amp;oacute;n explicados con anterioridad, agregaremos nuevas caracter&amp;iacute;sticas de formato para mejorar su presentaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Aplicar formato de porcentaje al eje horizontal &lt;/b&gt;&lt;/p&gt;
&lt;p&gt;En primer lugar haremos clic derecho en el eje horizontal de etiquetas seleccionando la opci&amp;oacute;n &amp;quot;Dar formato a eje&amp;quot;, que abrir&amp;aacute; la ventana de formato, en cuyo apartado &amp;quot;N&amp;uacute;mero&amp;quot; seleccionaremos la categor&amp;iacute;a de formato &amp;quot;Personalizado&amp;quot; y en el campo &amp;quot;C&amp;oacute;digo de formato&amp;quot; escribiremos la siguiente cadena de formato:&lt;/p&gt;
&lt;p&gt;0%;0%&lt;/p&gt;
&lt;p&gt;Haciendo clic en el bot&amp;oacute;n &amp;quot;Agregar&amp;quot;, la cadena se a&amp;ntilde;adir&amp;aacute; a la lista de cadenas personalizadas, de modo que al aceptar la ventana se aplicar&amp;aacute; el formato al eje horizontal de etiquetas.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_31.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Remarcando los bordes de las barras de poblaci&amp;oacute;n&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Seguidamente haremos clic sobre alguna de las barras del gr&amp;aacute;fico, volviendo a elegir la opci&amp;oacute;n &amp;quot;Dar formato a serie de datos&amp;quot;. En esta ocasi&amp;oacute;n, dentro del apartado &amp;quot;Color del borde&amp;quot; haremos clic en la opci&amp;oacute;n &amp;quot;L&amp;iacute;nea s&amp;oacute;lida&amp;quot;, seleccionando el color negro; mientras que en el apartado &amp;quot;Estilos del borde&amp;quot; asignaremos a la propiedad &amp;quot;Ancho&amp;quot; el valor &amp;quot;2 pto&amp;quot;. Esta operaci&amp;oacute;n la realizaremos para ambos grupos de barras del gr&amp;aacute;fico.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_32.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Despu&amp;eacute;s haremos clic derecho sobre las etiquetas de los rangos de edad, seleccionando la opci&amp;oacute;n &amp;quot;Dar formato a eje&amp;quot;. En esta ventana de formato asignaremos los mismos valores para las propiedades de color y estilo de borde que acabamos de utilizar para las barras del gr&amp;aacute;fico.&lt;/p&gt;
&lt;p&gt;Como resultado de estas acciones, el gr&amp;aacute;fico mostrar&amp;aacute; sus bordes con un contorno claramente remarcado.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_33.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Reubicando la posici&amp;oacute;n de la leyenda&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;En el momento de crear el gr&amp;aacute;fico, Excel sit&amp;uacute;a por defecto la leyenda (campo Sexo_DS) en el lado derecho. No obstante, es posible cambiar la ubicaci&amp;oacute;n de este elemento si queremos proporcionar m&amp;aacute;s espacio al dibujo de las barras de poblaci&amp;oacute;n. Para ello, haremos clic derecho en la leyenda y seleccionaremos la opci&amp;oacute;n &amp;quot;Formato de leyenda&amp;quot;, en la ventana de formato, dentro del apartado &amp;quot;Opciones de leyenda&amp;quot;, haremos clic en la opci&amp;oacute;n &amp;quot;Superior&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_34.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Como podemos apreciar, el gr&amp;aacute;fico ha ganado en superficie de dibujo, pero los indicadores de la leyenda han quedado colocados en orden inverso a las barras. Para solucionar este problema haremos clic en el bot&amp;oacute;n de campos de la leyenda (Sexo_DS), de forma que despleguemos sus opciones de filtro, donde seleccionaremos &amp;quot;Ordenar de Z a A&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_35.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Con esta acci&amp;oacute;n, los indicadores de leyenda quedar&amp;aacute;n colocados adecuadamente, pero ahora nos encontraremos con el inconveniente de que los colores de las barras han quedado invertidos, y hemos perdido el borde de las barras del gr&amp;aacute;fico.&lt;/p&gt;
&lt;p&gt;Restauraremos los bordes de las barras en la manera explicada anteriormente, mientras que en cuanto a los colores, para cada lado de la pir&amp;aacute;mide haremos clic derecho en una de las barras, y en la opci&amp;oacute;n &amp;quot;Relleno de forma&amp;quot;, cambiaremos el color actual por el que originalmente ten&amp;iacute;a el gr&amp;aacute;fico.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_36.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Para completar los ajustes que estamos realizando sobre la leyenda, arrastraremos &amp;eacute;sta hasta que quede situada al nivel del elemento superior de la pir&amp;aacute;mide, y aumentaremos su anchura, para que los indicadores queden m&amp;aacute;s separados.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_37.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Despejar el &amp;aacute;rea de campos y agregar t&amp;iacute;tulo&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Seguidamente haremos clic derecho en cualquiera de los botones de campos del gr&amp;aacute;fico y seleccionaremos la opci&amp;oacute;n &amp;quot;Ocultar todos los botones de campos en gr&amp;aacute;fico&amp;quot;. Con este movimiento impediremos que el usuario aplique filtros sobre el eje horizontal y/o vertical de la pir&amp;aacute;mide, manteniendo su estructura consistente y evitando as&amp;iacute; la posibilidad, por ejemplo, de ocultar rangos de edad o alguno de los sexos. No obstante, seguir&amp;aacute; existiendo tal posibilidad de filtro desde la tabla din&amp;aacute;mica.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_38.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Por otra parte, en el grupo de fichas &amp;quot;Herramientas del gr&amp;aacute;fico din&amp;aacute;mico&amp;quot; haremos clic en la ficha &amp;quot;Presentaci&amp;oacute;n&amp;quot;, y dentro del grupo &amp;quot;Etiquetas&amp;quot; haremos clic en la opci&amp;oacute;n &amp;quot;T&amp;iacute;tulo del gr&amp;aacute;fico&amp;quot;, que desplegar&amp;aacute; una serie de elementos entre los que elegiremos &amp;quot;Encima del gr&amp;aacute;fico&amp;quot;, a&amp;ntilde;adi&amp;eacute;ndose un cuadro de texto al gr&amp;aacute;fico, que editaremos para asignarle un t&amp;iacute;tulo. Llegados a este punto habremos completado el desarrollo de nuestra pir&amp;aacute;mide de poblaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_39.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Dinamizando los datos de la pir&amp;aacute;mide mediante segmentaciones&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Aunque hemos logrado el objetivo propuesto de crear una pir&amp;aacute;mide de poblaci&amp;oacute;n, resultar&amp;iacute;a interesante dotarla de cierto valor a&amp;ntilde;adido, tal y como vamos a hacer en este apartado.&lt;/p&gt;
&lt;p&gt;Si observamos el modelo de datos en la ventana de PowerPivot, caeremos en la cuenta de que todav&amp;iacute;a no hemos hecho uso de la informaci&amp;oacute;n que sobre zonificaci&amp;oacute;n sanitaria existe en el mismo, por lo que podemos aprovechar estos datos para construir un filtro que muestre la pir&amp;aacute;mide en base a la poblaci&amp;oacute;n de una o varias de estas zonas sanitarias.&lt;/p&gt;
&lt;p&gt;Las tablas din&amp;aacute;micas de PowerPivot, adem&amp;aacute;s del filtro tradicional, incorporan un nuevo tipo de filtro denominado &amp;quot;segmentaci&amp;oacute;n&amp;quot;, que adem&amp;aacute;s de la funcionalidad habitual de filtrado ofrece una interfaz de usuario m&amp;aacute;s flexible para la manipulaci&amp;oacute;n de los valores a tratar.&lt;/p&gt;
&lt;p&gt;Vamos a crear en nuestra pir&amp;aacute;mide una segmentaci&amp;oacute;n basada en la informaci&amp;oacute;n de zona. Para ello, en el panel de la lista de campos, arrastraremos el campo Zona_DS de la tabla Zona hasta el bloque &amp;quot;Segmentaciones de datos horizontales&amp;quot;, obteniendo como resultado una segmentaci&amp;oacute;n situada encima de la tabla din&amp;aacute;mica y el gr&amp;aacute;fico de pir&amp;aacute;mide.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_40.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Para filtrar los datos mediante la segmentaci&amp;oacute;n simplemente tenemos que seleccionar el nombre de la zona sanitaria que queramos emplear como filtro. Tambi&amp;eacute;n es posible filtrar simult&amp;aacute;neamente varias zonas manteniendo pulsada la tecla Ctrl, mientras vamos haciendo clic en las zonas a filtrar (como muestra la siguiente figura). Si queremos eliminar todos los filtros activos haremos clic en el icono situado a tal efecto en la parte superior derecha de la segmentaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_41.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Y llegados a este punto damos por finalizado el art&amp;iacute;culo, en el que a lo largo de sus dos entregas hemos mostrado el modo de construir una pir&amp;aacute;mide de poblaci&amp;oacute;n en Excel 2010, utilizando PowerPivot como herramienta de gesti&amp;oacute;n de los datos poblacionales. No obstante, la potencia de esta tecnolog&amp;iacute;a va m&amp;aacute;s all&amp;aacute; del mero tratamiento de la informaci&amp;oacute;n demogr&amp;aacute;fica, abarcando su campo de acci&amp;oacute;n a cualquier entorno en el que tengamos que realizar un an&amp;aacute;lisis con elevados vol&amp;uacute;menes de datos.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=199789" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item><item><title>Pirámides de población con PowerPivot. Preparación del entorno de datos (1)</title><link>http://geeks.ms/blogs/lmblanco/archive/2011/08/18/pir-225-mides-de-poblaci-243-n-con-powerpivot-preparaci-243-n-del-entorno-de-datos-1.aspx</link><pubDate>Thu, 18 Aug 2011 19:13:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:199678</guid><dc:creator>Luis Miguel Blanco</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/rsscomments.aspx?PostID=199678</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/lmblanco/commentapi.aspx?PostID=199678</wfw:comment><comments>http://geeks.ms/blogs/lmblanco/archive/2011/08/18/pir-225-mides-de-poblaci-243-n-con-powerpivot-preparaci-243-n-del-entorno-de-datos-1.aspx#comments</comments><description>&lt;p&gt;Una pir&amp;aacute;mide poblacional es una herramienta que nos permite analizar el estado y evoluci&amp;oacute;n de una poblaci&amp;oacute;n en funci&amp;oacute;n de su edad y sexo. Se trata de un elemento caracter&amp;iacute;stico en demograf&amp;iacute;a y estad&amp;iacute;stica, aunque sus aplicaciones tambi&amp;eacute;n abarcan campos tales como el sanitario, educativo, comercial, etc. Es por ello, que su integraci&amp;oacute;n en un sistema de informaci&amp;oacute;n perteneciente a alguna de las &amp;aacute;reas reci&amp;eacute;n mencionadas, supone un enriquecimiento sustancial en la calidad de los resultados obtenidos por los usuarios de tales sistemas.&lt;/p&gt;
&lt;p&gt;En el presente art&amp;iacute;culo abordaremos la construcci&amp;oacute;n de pir&amp;aacute;mides de poblaci&amp;oacute;n utilizando PowerPivot, un complemento para Excel 2010, que permite el acceso a or&amp;iacute;genes de datos de gran volumen, as&amp;iacute; como su posterior manejo y an&amp;aacute;lisis.&lt;/p&gt;
&lt;p&gt;Como ya apunt&amp;aacute;bamos en el art&amp;iacute;culo &lt;a href="http://geeks.ms/blogs/lmblanco/archive/2011/07/18/generaci-243-n-de-datos-demogr-225-ficos-desde-sql-server.aspx"&gt;Generaci&amp;oacute;n de datos demogr&amp;aacute;ficos desde SQL Server&lt;/a&gt;, publicado en este mismo blog, nuestro objetivo actual (utilizando la base de datos PiramidePoblacion creada en el mencionado art&amp;iacute;culo) consistir&amp;aacute; en construir un gr&amp;aacute;fico que &amp;nbsp;represente una pir&amp;aacute;mide de poblaci&amp;oacute;n similar a la que vemos&amp;nbsp; en la siguiente figura.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_01.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;La primera parte del art&amp;iacute;culo estar&amp;aacute; dedicada a la preparaci&amp;oacute;n del modelo de datos de PowerPivot: conexi&amp;oacute;n contra un origen de datos, carga y creaci&amp;oacute;n de una tabla din&amp;aacute;mica para analizar las cifras de poblaci&amp;oacute;n. La segunda parte la destinaremos a la construcci&amp;oacute;n del gr&amp;aacute;fico que represente a la pir&amp;aacute;mide de poblaci&amp;oacute;n, partiendo de los datos sobre los que hemos trabajado en la primera entrega.&lt;/p&gt;
&lt;p&gt;Al igual que en el art&amp;iacute;culo mencionado anteriormente, quiero agradecer nuevamente a los integrantes del Servicio de Informes de Salud y Estudios (Subdirecci&amp;oacute;n de Promoci&amp;oacute;n de la Salud y Prevenci&amp;oacute;n, DG Atenci&amp;oacute;n Primaria, Consejer&amp;iacute;a Sanidad CM): Jenaro Astray Mochales, Mar&amp;iacute;a Felicitas Dom&amp;iacute;nguez Berj&amp;oacute;n, Mar&amp;iacute;a Dolores Esteban Vasallo, Beatriz Elvira Rodr&amp;iacute;guez y en especial a Ricard G&amp;egrave;nova Maleras, el soporte y orientaci&amp;oacute;n recibido sobre los conceptos demogr&amp;aacute;ficos necesarios con los que poder desarrollar apropiadamente una pir&amp;aacute;mide de poblaci&amp;oacute;n utilizando Excel 2010 en combinaci&amp;oacute;n con PowerPivot. Adem&amp;aacute;s de todo esto, Ricard ha accedido muy gustosamente a realizar una estupenda labor de revisi&amp;oacute;n de este art&amp;iacute;culo, con lo que el agradecimiento va por partida doble.&lt;/p&gt;
&lt;p&gt;Igualmente quisiera expresar mi agradecimiento a Enrique Barcel&amp;oacute; por todos sus estupendos trucos sobre desarrollo OLAP, que comparte con el equipo de trabajo, y que hacen un poco m&amp;aacute;s f&amp;aacute;cil nuestra labor de desarrollo en estas tareas del Business Intelligence.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Un poco de teor&amp;iacute;a&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Pero antes de entrar de lleno en su proceso de creaci&amp;oacute;n, vamos a proporcionar unos breves apuntes te&amp;oacute;ricos sobre las pir&amp;aacute;mides de poblaci&amp;oacute;n, que nos permitan entender mejor cu&amp;aacute;les son sus principales caracter&amp;iacute;sticas y la informaci&amp;oacute;n que de ellas podemos obtener y analizar.&lt;/p&gt;
&lt;p&gt;En esencia, una pir&amp;aacute;mide de poblaci&amp;oacute;n es un doble histograma que representa la distribuci&amp;oacute;n por edad y sexo de los efectivos de una poblaci&amp;oacute;n, bien en cifras absolutas, bien como porcentaje sobre la poblaci&amp;oacute;n total.&lt;/p&gt;
&lt;p&gt;Si estamos interesados en obtener una informaci&amp;oacute;n m&amp;aacute;s detallada acerca de los aspectos conceptuales que rodean a las pir&amp;aacute;mides de poblaci&amp;oacute;n, la ayuda del programa &lt;a href="http://www.sergas.es/MostrarContidos_N3_T01.aspx?IdPaxina=62714"&gt;Epidat 4.0&lt;/a&gt; puede resultarnos de utilidad. Se trata de una aplicaci&amp;oacute;n desarrollada por la &lt;a href="http://www.sergas.es/MostrarContidos_N3_T01.aspx?IdPaxina=62713"&gt;Consejer&amp;iacute;a de Sanidad de la Xunta de Galicia&lt;/a&gt; y la &lt;a href="http://new.paho.org/blogs/esp/?p=694"&gt;Organizaci&amp;oacute;n Panamericana de la Salud&lt;/a&gt; (OPS, Washington), de cuya documentaci&amp;oacute;n citamos a continuaci&amp;oacute;n algunos de los puntos m&amp;aacute;s importantes en relaci&amp;oacute;n con el tema que nos ocupa. En primer lugar comenzaremos con algunas nociones relativas a la construcci&amp;oacute;n de la pir&amp;aacute;mide de poblaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&amp;quot;El mejor modo de visualizar la distribuci&amp;oacute;n por sexo y edad de una poblaci&amp;oacute;n es, sin duda, la pir&amp;aacute;mide de poblaci&amp;oacute;n, verdadero icono de la demograf&amp;iacute;a. Una pir&amp;aacute;mide es un doble histograma que permite, con un solo golpe de vista, hacerse una idea clara no s&amp;oacute;lo acerca de las caracter&amp;iacute;sticas generales de la poblaci&amp;oacute;n (joven, envejecida, con alg&amp;uacute;n desequilibrio en funci&amp;oacute;n del sexo) sino tambi&amp;eacute;n sobre particularidades espec&amp;iacute;ficas que remiten a alg&amp;uacute;n acontecimiento concreto concerniente a la poblaci&amp;oacute;n objeto de estudio.&lt;/p&gt;
&lt;p&gt;Usualmente las pir&amp;aacute;mides de poblaci&amp;oacute;n se construyen siguiendo varias convenciones y reglas:&lt;/p&gt;
&lt;p&gt;- representar a los hombres a la izquierda y a las mujeres a la derecha del eje central,&lt;/p&gt;
&lt;p&gt;- ubicar las edades de manera que cuanto m&amp;aacute;s bajas sean, m&amp;aacute;s cerca est&amp;eacute;n de la base y viceversa,&lt;/p&gt;
&lt;p&gt;- mantener cierta proporcionalidad entre base y altura (3 anchuras por 2 alturas, o 4 por 3, aproximadamente),&lt;/p&gt;
&lt;p&gt;- respetar la misma escala a ambos lados del eje central (para favorecer la comparaci&amp;oacute;n entre sexos),&lt;/p&gt;
&lt;p&gt;- representar el peso de cada intervalo etario por la superficie de cada barra del histograma, no por su longitud, algo especialmente importante cuando se trabaja con grupos de edad desiguales,&lt;/p&gt;
&lt;p&gt;- pueden construirse con valores absolutos, pero es preferible hacerlo con las proporciones de cada edad y sexo respecto de la poblaci&amp;oacute;n total. &lt;/p&gt;
&lt;p&gt;El &amp;uacute;ltimo punto es importante y diferencia a la pir&amp;aacute;mide de los indicadores de estructura [proporci&amp;oacute;n de j&amp;oacute;venes o ancianos, &amp;iacute;ndice de envejecimiento, etc.], que se calculan separadamente sobre el total de cada sexo respectivo. En el caso de la pir&amp;aacute;mide de poblaci&amp;oacute;n, usar como denominador de las proporciones a la poblaci&amp;oacute;n total de ambos sexos reunidos garantiza la comparabilidad no s&amp;oacute;lo de la distribuci&amp;oacute;n por edad, sino tambi&amp;eacute;n por sexo&amp;quot;.&lt;/p&gt;
&lt;p&gt;Y finalizaremos con aquellas cuestiones relacionadas con la interpretaci&amp;oacute;n de la pir&amp;aacute;mide.&lt;/p&gt;
&lt;p&gt;&amp;quot;Una pir&amp;aacute;mide por sexo y edad resume la historia demogr&amp;aacute;fica de una poblaci&amp;oacute;n de por lo menos los cien a&amp;ntilde;os anteriores a la fecha de referencia (el tiempo que tarda, aproximadamente, una generaci&amp;oacute;n en pasar de la base a la cima de la pir&amp;aacute;mide). En ocasiones, el efecto indirecto de algunos acontecimientos demogr&amp;aacute;ficos es visible m&amp;aacute;s all&amp;aacute; de ese salto de un siglo (por ejemplo, el impacto del profundo descenso de la fecundidad de las &amp;uacute;ltimas d&amp;eacute;cadas experimentado por muchas poblaciones se apreciar&amp;aacute;, sin duda, en las pir&amp;aacute;mides de la primera mitad del siglo XXII). Una pir&amp;aacute;mide por edades simples [edad por edad: 0, 1, 2, 3 ... 99, 100 ...] permite un an&amp;aacute;lisis m&amp;aacute;s preciso que otra realizada por grupos de edades agregadas (quinquenales, decenales), pero corre tambi&amp;eacute;n el riesgo de verse afectada por problemas de calidad de los registros, o ser vulnerable a la inestabilidad de las distribuciones en poblaciones peque&amp;ntilde;as.&lt;/p&gt;
&lt;p&gt;La primera percepci&amp;oacute;n de una pir&amp;aacute;mide permite identificar los rasgos generales de la poblaci&amp;oacute;n representada: una pir&amp;aacute;mide de base ancha y que se estrecha r&amp;aacute;pidamente da idea de una poblaci&amp;oacute;n joven, con una alta proporci&amp;oacute;n de ni&amp;ntilde;os y adolescentes, y baja de adultos y ancianos, resultado de una alta natalidad y mortalidad. Inversamente, una pir&amp;aacute;mide con perfil estrecho en la base y ancho en el centro y la cima representa una estructura madura o envejecida. Cuanto mayor es la esperanza de vida de una poblaci&amp;oacute;n, mayor suele ser la desigualdad por sexo en la cima de la pir&amp;aacute;mide (m&amp;aacute;s llena por el lado de las mujeres, por su mayor nivel de supervivencia).&lt;/p&gt;
&lt;p&gt;La pir&amp;aacute;mide no da respuestas por s&amp;iacute; misma, sino que propicia que se planteen preguntas pertinentes. Las explicaciones para su perfil deben buscarse en la historia, en los avatares sociales, pol&amp;iacute;ticos, econ&amp;oacute;micos, que generan consecuencias en el devenir demogr&amp;aacute;fico -es decir, en la fecundidad, la mortalidad o la migraci&amp;oacute;n, que son los fen&amp;oacute;menos que modelan el contorno y fijan el tama&amp;ntilde;o de una poblaci&amp;oacute;n- y que tienen una interpretaci&amp;oacute;n en funci&amp;oacute;n de la triple perspectiva temporal: edad, periodo y cohorte&amp;quot;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Incorporando los datos a PowerPivot&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Gracias a VertiPaq, el motor de procesamiento de datos de PowerPivot, podemos conseguir una potencia y velocidad sin precedentes en la manipulaci&amp;oacute;n, filtrado, creaci&amp;oacute;n de expresiones de l&amp;oacute;gica de negocio, y en definitiva, en todas aquellas operaciones anal&amp;iacute;ticas que debamos realizar sobre un modelo de datos creado con esta herramienta.&lt;/p&gt;
&lt;p&gt;El siguiente &lt;a href="http://www.powerpivot.com/"&gt;enlace&lt;/a&gt; proporciona acceso a la p&amp;aacute;gina principal de PowerPivot, desde donde podremos descargarlo, para posteriormente instalarlo en nuestra m&amp;aacute;quina, de forma que podamos seguir los ejemplos del art&amp;iacute;culo.&lt;/p&gt;
&lt;p&gt;Una vez que hayamos instalado PowerPivot iniciaremos Excel 2010, cre&amp;aacute;ndose una nueva hoja de c&amp;aacute;lculo a la que daremos el nombre PiramidePoblacion.xlsx. En la cinta de opciones dispondremos ahora de una nueva ficha con el nombre &amp;quot;PowerPivot&amp;quot;. Al hacer clic en la misma seleccionaremos la opci&amp;oacute;n &amp;quot;Ventana de PowerPivot&amp;quot;, perteneciente al grupo &amp;quot;Iniciar&amp;quot;, lo que abrir&amp;aacute; la mencionada ventana de trabajo de PowerPivot, en la que definiremos la estructura de tablas que vamos a utilizar, o &amp;quot;modelo de datos&amp;quot;, tal y c&amp;oacute;mo se denomina dentro del contexto de PowerPivot.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_02.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_02.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A continuaci&amp;oacute;n, en la pesta&amp;ntilde;a &amp;quot;P&amp;aacute;gina principal&amp;quot; de la ventana de PowerPivot, nos conectaremos a la base de datos mediante la opci&amp;oacute;n &amp;quot;Desde base de datos | De SQL Server&amp;quot;, situada en el grupo &amp;quot;Obtener datos externos&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_03.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_03.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Esta acci&amp;oacute;n iniciar&amp;aacute; el asistente para importar tablas, en el que indicaremos el origen de datos al que nos queremos conectar.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_04.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_04.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Una fuente de datos v&amp;aacute;lida para elaborar una pir&amp;aacute;mide de poblaci&amp;oacute;n ha de tener como m&amp;iacute;nimo informaci&amp;oacute;n acerca del sexo y edad de la poblaci&amp;oacute;n, como es el caso de nuestra base de datos PiramidePoblacion. Adicionalmente, y como forma de enriquecer el an&amp;aacute;lisis a realizar, la base de datos puede disponer de informaci&amp;oacute;n complementaria como pudiera ser la zonificaci&amp;oacute;n sanitaria, nacionalidad de la poblaci&amp;oacute;n, etc.&lt;/p&gt;
&lt;p&gt;Tras elegir la base de datos PiramidePoblacion, el siguiente paso nos ofrecer&amp;aacute; una lista de las tablas y vistas que podremos importar, donde marcaremos las siguientes: Edad, Poblaci&amp;oacute;n, Sexo y Zona, comenzando la importaci&amp;oacute;n al hacer clic en el bot&amp;oacute;n &amp;quot;Finalizar&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_05.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_05.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Si la importaci&amp;oacute;n se desarrolla correctamente, el asistente mostrara una ventana resumen del proceso.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_06.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_06.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Una vez terminada la incorporaci&amp;oacute;n de datos haremos clic en &amp;quot;Cerrar&amp;quot; para volver a la ventana de PowerPivot, donde hallaremos organizadas en diversas pesta&amp;ntilde;as cada una de las tablas importadas.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_07.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;An&amp;aacute;lisis mediante tabla din&amp;aacute;mica&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Antes de pasar a la fase de construcci&amp;oacute;n de la pir&amp;aacute;mide de poblaci&amp;oacute;n, vamos a utilizar una tabla din&amp;aacute;mica de PowerPivot para analizar las cifras del modelo de datos, por lo que situados en su ventana de trabajo haremos clic en la opci&amp;oacute;n &amp;quot;PivotTable&amp;quot;, perteneciente al grupo &amp;quot;Informes&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src="http://geeks.ms/cfs-filesystemfile.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_08.jpg" border="0" style="max-width:550px;" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Esta acci&amp;oacute;n nos posicionar&amp;aacute; en la ventana de Excel, donde se abrir&amp;aacute; un di&amp;aacute;logo en el que elegiremos la hoja de c&amp;aacute;lculo en la que se ubicar&amp;aacute; la tabla din&amp;aacute;mica.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_09.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_09.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;En nuestro caso seleccionaremos la primera opci&amp;oacute;n y aceptaremos el di&amp;aacute;logo, cre&amp;aacute;ndose la tabla din&amp;aacute;mica en una nueva hoja c&amp;aacute;lculo&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_10.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_10.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Desde el panel &amp;quot;Lista de campos de PowerPivot&amp;quot; tenemos a nuestra disposici&amp;oacute;n los campos de las tablas del modelo de datos, que situaremos en las diferentes zonas de la tabla din&amp;aacute;mica (etiquetas de filas, columnas, valores, etc.) para llevar a cabo nuestras operaciones de an&amp;aacute;lisis. Utilizaremos para ello un estilo de trabajo muy semejante al que emplear&amp;iacute;amos si estuvi&amp;eacute;ramos consultando un cubo OLAP, ya que el manejo de los campos de PowerPivot en este sentido es similar al que podemos realizar con las dimensiones y medidas de un cubo de datos cuando es consultado desde Excel.&lt;/p&gt;
&lt;p&gt;Vamos a comenzar por una consulta sencilla, consistente en contar los registros de la tabla Poblaci&amp;oacute;n, agrupando la informaci&amp;oacute;n por rangos de edad, los cuales situaremos en las filas de la tabla din&amp;aacute;mica.&lt;/p&gt;
&lt;p&gt;El recuento de registros lo realizaremos mediante una expresi&amp;oacute;n &lt;a href="http://social.technet.microsoft.com/wiki/contents/articles/powerpivot-data-analysis-expressions-dax-language.aspx"&gt;DAX&lt;/a&gt; (el lenguaje de consultas de PowerPivot) situada en una medida calculada, que crearemos seleccionando la opci&amp;oacute;n &amp;quot;Nueva medida&amp;quot;, perteneciente al grupo &amp;quot;Medidas&amp;quot; de la ficha &amp;quot;PowerPivot&amp;quot;. Esta medida la aplicaremos sobre la tabla Poblaci&amp;oacute;n, por lo que deberemos estar previamente posicionados en la misma, dentro del panel de la lista de campos.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_11.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_11.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Al seleccionar esta opci&amp;oacute;n se abrir&amp;aacute; la ventana &amp;quot;Configuraci&amp;oacute;n de medida&amp;quot;, en la que dentro del cuadro de texto reservado para la f&amp;oacute;rmula escribiremos la siguiente expresi&amp;oacute;n:&lt;/p&gt;
&lt;p&gt;=COUNTROWS(Poblacion)&lt;/p&gt;
&lt;p&gt;La funci&amp;oacute;n COUNTROWS, como su nombre indica, cuenta las filas de la tabla pasada como par&amp;aacute;metro. Para terminar la creaci&amp;oacute;n de nuestra medida le daremos el nombre &amp;quot;RecuentoPoblacion&amp;quot; y haremos clic en &amp;quot;Aceptar&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_12.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_12.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Nada m&amp;aacute;s terminar de crear la medida, &amp;eacute;sta se a&amp;ntilde;adir&amp;aacute; autom&amp;aacute;ticamente a la lista de campos de la tabla Poblaci&amp;oacute;n y al bloque &amp;quot;Valores&amp;quot;, visualiz&amp;aacute;ndose en la tabla din&amp;aacute;mica el n&amp;uacute;mero total de filas de la tabla.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_13.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_13.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A continuaci&amp;oacute;n seleccionaremos, en el panel de la lista de campos, el campo Edad_Grupo de la tabla Edad, lo que situar&amp;aacute; autom&amp;aacute;ticamente al mencionado campo en el bloque &amp;quot;Etiquetas de fila&amp;quot;. Si este no fuera el comportamiento obtenido, arrastraremos manualmente el campo hasta colocarlo en dicho bloque.&lt;/p&gt;
&lt;p&gt;Como consecuencia de la acci&amp;oacute;n anterior la tabla din&amp;aacute;mica se ver&amp;aacute; actualizada, mostr&amp;aacute;ndose en el eje de las filas los valores del campo Edad_Grupo. Respecto a las cifras de la medida RecuentoPoblacion, &amp;eacute;stas deber&amp;iacute;an repartirse entre los tramos de cada edad, para as&amp;iacute; reflejar el n&amp;uacute;mero de registros (poblaci&amp;oacute;n) correspondiente a cada uno de dichos tramos. Sin embargo, como vemos en la siguiente figura, es algo que no est&amp;aacute; ocurriendo, ya que la medida muestra el mismo valor para todas las filas, lo cual es incorrecto.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_14.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_14.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Relaciones entre las tablas del modelo&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Observando el panel de campos vemos que PowerPivot ya se ha percatado del problema que acabamos de comentar, porque en la parte superior de dicho panel aparece un aviso, que nos informa acerca de que puede ser necesaria una relaci&amp;oacute;n entre las tablas que se est&amp;aacute;n utilizando para componer la consulta de la tabla din&amp;aacute;mica.&lt;/p&gt;
&lt;p&gt;Este problema no habr&amp;iacute;a tenido lugar si hubiesen existido las oportunas relaciones entre las tablas de la base de datos, aunque como ya dijimos en el art&amp;iacute;culo sobre la creaci&amp;oacute;n de la base de datos de poblaci&amp;oacute;n, dichas relaciones no fueron creadas intencionadamente, para as&amp;iacute; demostrar que tambi&amp;eacute;n es posible hacerlo desde PowerPivot, como veremos a continuaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;Para dejar que PowerPivot detecte autom&amp;aacute;ticamente la relaci&amp;oacute;n que necesita, haremos clic en el bot&amp;oacute;n &amp;quot;Crear&amp;quot; que aparece junto al aviso mostrado en el panel de campos. Como resultado se abrir&amp;aacute; una ventana encargada de crear la oportuna relaci&amp;oacute;n, ofreci&amp;eacute;ndonos informaci&amp;oacute;n adicional sobre la misma a trav&amp;eacute;s de los enlaces &amp;quot;Detalles&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_15.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_15.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Una vez creada la relaci&amp;oacute;n, &amp;eacute;sta ser&amp;aacute; aplicada inmediatamente, sin intervenci&amp;oacute;n del usuario, sobre la tabla din&amp;aacute;mica, que de esta forma ya mostrar&amp;aacute; correctamente los valores de la medida agrupados por edad.&lt;/p&gt;
&lt;p&gt;Tambi&amp;eacute;n es posible crear manualmente las relaciones entre las tablas del modelo de datos utilizando la ventana de trabajo de PowerPivot. Para ello haremos clic en la opci&amp;oacute;n &amp;quot;Crear relaci&amp;oacute;n&amp;quot;, perteneciente al grupo &amp;quot;Relaciones&amp;quot;, que est&amp;aacute; situado en la ficha &amp;quot;Dise&amp;ntilde;o&amp;quot; de la mencionada ventana.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_16.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_16.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Esta opci&amp;oacute;n abrir&amp;aacute; una ventana con el mismo nombre, en la que seleccionaremos la tabla y columna que representar&amp;aacute;n el origen y destino de la relaci&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_17.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_17.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;De esta forma estableceremos dos nuevas relaciones, que tendr&amp;aacute;n a la tabla Poblaci&amp;oacute;n como origen y a las tablas Sexo y Zona como destino. Adicionalmente, desde la opci&amp;oacute;n &amp;quot;Administrar relaciones&amp;quot; podemos ver un resumen de las relaciones creadas as&amp;iacute; como gestionarlas (crear, editar, eliminar, etc.).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_18.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_18.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Estos cambios que acabamos de realizar en la ventana de PowerPivot pueden afectar directa o indirectamente a los datos que estamos presentando en la tabla din&amp;aacute;mica; por dicho motivo, al retornar a la ventana de Excel veremos un aviso al respecto en el panel de campos, donde haremos clic en el bot&amp;oacute;n &amp;quot;Actualizar&amp;quot;, para refrescar los datos con los que estamos trabajando.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_19.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_19.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Agregando datos en el eje de columnas&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Solucionado el problema de las relaciones, ahora es el momento de a&amp;ntilde;adir nuevos datos en las columnas de la tabla din&amp;aacute;mica mediante el campo Sexo_DS de la tabla Sexo.&lt;/p&gt;
&lt;p&gt;Al&amp;nbsp; ser seleccionado, este campo se situar&amp;aacute; por defecto en el bloque &amp;quot;Etiquetas de fila&amp;quot;, de modo que tendremos que moverlo manualmente hasta el bloque &amp;quot;Etiquetas de columna&amp;quot;; o bien al hacer clic en &amp;eacute;l lo arrastraremos directamente hasta el bloque de etiquetas de columna.&lt;/p&gt;
&lt;p&gt;Adicionalmente, daremos formato a las celdas num&amp;eacute;ricas haciendo clic derecho en cualquiera de ellas y seleccionando la opci&amp;oacute;n &amp;quot;Formato de n&amp;uacute;mero&amp;quot;, en el cuadro de di&amp;aacute;logo de formato definiremos &amp;eacute;ste sin decimales y con separador de miles.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_20.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_20.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Una vez realizadas estas operaciones, la tabla din&amp;aacute;mica ya mostrar&amp;aacute; los datos de poblaci&amp;oacute;n de manera acorde a los requerimientos planteados.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_21.jpg"&gt;&lt;img src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/lmblanco.ImagenesArticulos.201108/PiramidesPoblacionPowerPivot_5F00_21.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Llegados a este punto concluimos la primera parte del art&amp;iacute;culo. En la siguiente entrega alcanzaremos nuestro objetivo de crear un gr&amp;aacute;fico que represente la pir&amp;aacute;mide de poblaci&amp;oacute;n utilizando los datos que hemos preparado con PowerPivot.&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=199678" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/SQL+Server/default.aspx">SQL Server</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Excel/default.aspx">Excel</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/PowerPivot/default.aspx">PowerPivot</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/Data+Warehouse/default.aspx">Data Warehouse</category><category domain="http://geeks.ms/blogs/lmblanco/archive/tags/DAX/default.aspx">DAX</category></item></channel></rss>