<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8486191632104654344</id><updated>2012-02-16T20:26:59.027-08:00</updated><title type='text'>MDX and DAX topics</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://mdxdax.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://mdxdax.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jeffrey Wang</name><uri>http://www.blogger.com/profile/09745744072887789758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8486191632104654344.post-2055545184624214162</id><published>2012-01-31T23:38:00.000-08:00</published><updated>2012-01-31T23:38:55.602-08:00</updated><title type='text'>DAX Query Plan, Part 2, Operator Properties</title><content type='html'>&lt;div class="WordSection1"&gt;&lt;a href="http://mdxdax.blogspot.com/2011/12/dax-query-plan-part-1-introduction.html"&gt;&lt;span style="color: blue;"&gt;Last time&lt;/span&gt;&lt;/a&gt; we learned that DAX Query Plans are tree structures formatted as indented text with each text line representing a single operator node in a tree. A text line begins with an operator name followed by a colon and then properties of the operator. Today we study the operator properties. You will see that for the four types of operators, &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;ScaLogOp&lt;/i&gt;&lt;/span&gt;, &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;RelLogOp&lt;/i&gt;&lt;/span&gt;, &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;LookupPhyOp&lt;/i&gt;&lt;/span&gt;, and &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;IterPhyOp&lt;/i&gt;&lt;/span&gt;, each type has a fixed set of common properties, and an individual operator may contain extra properties to provide supplemental information. We’ll focus on the semantics of the common properties in this post.&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;List of Columns&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;In a DAX Query Plan, a list of columns is shown as a list of comma-delimited column numbers in a pair of parentheses plus a list of comma-delimited fully-qualified column names in another pair of parentheses, see Figure 1. In a degenerate case, two pairs of empty parentheses, (&lt;span class="GramE"&gt;)(&lt;/span&gt;), represent an empty list. Note that some properties, like &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;LookupCols&lt;/i&gt;&lt;/span&gt; and &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;IterCols&lt;/i&gt;&lt;/span&gt;, are not shown in the plan when they contain no columns, but other properties, like &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;DependOnCols&lt;/i&gt;&lt;/span&gt; and &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;RequiredCols&lt;/i&gt;&lt;/span&gt;, are always shown even when their list of columns is empty.&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-wi5TXq5wC-U/TyjeFWIBakI/AAAAAAAAAGw/Uub7cN3hiSg/s1600/ListOfColumns.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="106" src="http://2.bp.blogspot.com/-wi5TXq5wC-U/TyjeFWIBakI/AAAAAAAAAGw/Uub7cN3hiSg/s400/ListOfColumns.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;v:shapetype coordsize="21600,21600" filled="f" id="_x0000_t75" o:preferrelative="t" o:spt="75" path=" m@4@5 l@4@11@9@11@9@5 xe" stroked="f"&gt;&lt;v:stroke joinstyle="miter"&gt;&lt;/v:stroke&gt;&lt;v:formulas&gt;&lt;v:f eqn="if lineDrawn pixelLineWidth 0 "&gt;&lt;/v:f&gt;&lt;v:f eqn="sum @0 1 0 "&gt;&lt;/v:f&gt;&lt;v:f eqn="sum 0 0 @1 "&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @2 1 2 "&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @3 21600 pixelWidth "&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @3 21600 pixelHeight "&gt;&lt;/v:f&gt;&lt;v:f eqn="sum @0 0 1 "&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @6 1 2 "&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @7 21600 pixelWidth "&gt;&lt;/v:f&gt;&lt;v:f eqn="sum @8 21600 0 "&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @7 21600 pixelHeight "&gt;&lt;/v:f&gt;&lt;v:f eqn="sum @10 21600 0 "&gt;&lt;/v:f&gt;&lt;/v:formulas&gt;&lt;v:path gradientshapeok="t" o:connecttype="rect" o:extrusionok="f"&gt;&lt;/v:path&gt;&lt;o:lock aspectratio="t" v:ext="edit"&gt;&lt;/o:lock&gt;&lt;/v:shapetype&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;Column numbers are helpful when you need to disambiguate two separate references to the same column. When you execute Query 1 against &lt;a href="http://msftdbprodsamples.codeplex.com/releases/view/55330"&gt;&lt;span style="color: blue;"&gt;the tabular &lt;span class="SpellE"&gt;AdventureWorks&lt;/span&gt; database&lt;/span&gt;&lt;/a&gt;, the logical plan, shown in Figure 2, assigns different numbers to column &lt;span class="GramE"&gt;‘Date’[&lt;/span&gt;Month]: number 1 refers to the column in the outer table scan and number 2 refers to the column in the inner table scan. Column numbers are not chosen to be globally unique, but rather unique within a local context.&lt;/div&gt;&lt;pre class="code" style="margin-left: 15px;"&gt;// Query 1&lt;br /&gt;define measure 'Internet Sales'[Total Sales Amount] = Sum([Sales Amount])&lt;br /&gt;evaluate&lt;br /&gt;  calculatetable(&lt;br /&gt;    addcolumns(&lt;br /&gt;      values('Date'[Month]),           -- outer scan&lt;br /&gt;      "YTD",&lt;br /&gt;      calculate([Total Sales Amount],&lt;br /&gt;          filter(&lt;br /&gt;            All('Date'[Month]),        -- inner scan&lt;br /&gt;            'Date'[Month]              -- refer to inner scan&lt;br /&gt;            &amp;lt;=&lt;br /&gt;            earlier('Date'[Month])     -- refer to outer scan&lt;br /&gt;          )&lt;br /&gt;      )&lt;br /&gt;    ),&lt;br /&gt;    'Date'[Calendar Year] = 2003&lt;br /&gt;  )&lt;br /&gt;&lt;/pre&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-SYR5lvvYsl8/Tyjehz8vcUI/AAAAAAAAAG4/uRcS0DDA3YM/s1600/ColumnNumbers.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="108" src="http://4.bp.blogspot.com/-SYR5lvvYsl8/Tyjehz8vcUI/AAAAAAAAAG4/uRcS0DDA3YM/s400/ColumnNumbers.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;Common Properties of Logical Plan Nodes&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;Here are the properties common to all scalar logical operators (&lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;ScaLogOp&lt;/i&gt;&lt;/span&gt;):&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"&gt;&lt;span style="mso-list: Ignore;"&gt;·&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;DependOnCols&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.25in;"&gt;&lt;span style="font-family: Calibri;"&gt;Marks columns from the left-sideof a tree on which the current logical operator depends. The current operatormay return a different value for each distinct combination of values of &lt;i style="mso-bidi-font-style: normal;"&gt;DependOnCols&lt;/i&gt;. Some table scanningfunctions, e.g. &lt;i style="mso-bidi-font-style: normal;"&gt;AddColumns&lt;/i&gt; and &lt;i style="mso-bidi-font-style: normal;"&gt;Filter&lt;/i&gt;, create a row context using itsleft child subtree and then evaluate the value of its right child subtree inthis context. This creates a dependency of the right child subtree on somecolumns from the left child subtree. &lt;i style="mso-bidi-font-style: normal;"&gt;DependOnCols&lt;/i&gt;captures this correlation between the two sides of a tree. Figure 3 shows anexample where a &lt;i style="mso-bidi-font-style: normal;"&gt;ScaLogOp&lt;/i&gt; subtree onthe right depends on some columns from two &lt;i style="mso-bidi-font-style: normal;"&gt;RelLogOp&lt;/i&gt;subtrees on the left. At the bottom level of a tree, &lt;i style="mso-bidi-font-style: normal;"&gt;DependOnCols&lt;/i&gt;&amp;nbsp;are established by either an explicit reference to acolumn on the left or by a leaf table scan that joins directly or indirectly(through SetFilter arguments of &lt;i style="mso-bidi-font-style: normal;"&gt;Calculate&lt;/i&gt;function) to columns on the left. &lt;i style="mso-bidi-font-style: normal;"&gt;DependOnCols&lt;/i&gt;are then propagated up through intermediate parent nodes to the root node of theright subtree. Since DAX automatic cross-table filtering rules can be trickysometimes, beginners can use this property to help them figure out whethertheir measures have the correct dependencies on external row contexts.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"&gt;&lt;span style="mso-list: Ignore;"&gt;·&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;Data type&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.25in;"&gt;&lt;span style="font-family: Calibri;"&gt;One of the six data types DAXsupports. Values returned by the operator must be either of this data type orbe the BLANK value.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"&gt;&lt;span style="mso-list: Ignore;"&gt;·&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;DominantValue&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.25in;"&gt;&lt;span style="font-family: Calibri;"&gt;Captures the sparsity of a scalarlogical operator. When &lt;i style="mso-bidi-font-style: normal;"&gt;DominantValue&lt;/i&gt;is NONE, the operator is dense, otherwise, it is sparse. When a scalar subtreeis sparse, DAX Formula Engine may pick a physical plan that can be orders ofmagnitudes faster than a naïve physical plan. For example, if the predicatechild operator of a &lt;i style="mso-bidi-font-style: normal;"&gt;Filter&lt;/i&gt; operatorhas a &lt;i style="mso-bidi-font-style: normal;"&gt;DominantValue&lt;/i&gt; of FALSE, DAXFormula Engine can construct an iterator physical plan for the predicatesubtree that automatically skips large chunks of rows which would otherwisereturn FALSE and be thrown away any way by the &lt;i style="mso-bidi-font-style: normal;"&gt;Filter&lt;/i&gt; operator.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;For userscoming from MDX background, this reminds them of the huge performancedifference between block mode vs. cell-by-cell mode. The technique to derivethe sparsity of a scalar subtree is very sophisticated and beyond the scope ofthis post. It’s enough to know that a sparse scalar operator is the key togreat performance in many common query patterns.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Fhwz5f7tPC0/TyjfGJrTNzI/AAAAAAAAAHA/gCz5NqkZ9bQ/s1600/DependOnCols.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/-Fhwz5f7tPC0/TyjfGJrTNzI/AAAAAAAAAHA/gCz5NqkZ9bQ/s320/DependOnCols.png" width="292" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;Here are properties common to all relational logical operators (&lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;RelLogOp&lt;/i&gt;&lt;/span&gt;):&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"&gt;&lt;span style="mso-list: Ignore;"&gt;·&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;DependOnCols&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.25in;"&gt;&lt;span style="font-family: Calibri;"&gt;Identical to the same namedproperty of &lt;i style="mso-bidi-font-style: normal;"&gt;ScaLogOp&lt;/i&gt;. The currentoperator may return a different table for each distinct combination of valuesof &lt;i style="mso-bidi-font-style: normal;"&gt;DependOnCols&lt;/i&gt;.&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"&gt;&lt;span style="mso-list: Ignore;"&gt;·&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;Range of column numbers&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.25in;"&gt;&lt;span style="font-family: Calibri;"&gt;Although a relation may containmany columns in its heading, DAX Formula Engine is smart enough to derive theminimal subset of columns, see &lt;i style="mso-bidi-font-style: normal;"&gt;RequiredCols&lt;/i&gt;property, which are needed to answer a query. To save space, DAX Query Plandoes not list all columns in the relation header, instead, it assignscontinuous column numbers to all columns in the relation header and only shows&amp;lt;beginning column name&amp;gt;-&amp;lt;ending column name&amp;gt; as a part of the plan.Note that this property may be missing when a relation has no column at all.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"&gt;&lt;span style="mso-list: Ignore;"&gt;·&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;RequiredCols&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.25in;"&gt;&lt;span style="font-family: Calibri;"&gt;This is the union of &lt;i style="mso-bidi-font-style: normal;"&gt;DependOnCols&lt;/i&gt; and the subset of columnsfrom the relation header which are needed to answer a query. For example, whenyou examine the logical plan, shown in Figure 4, which corresponds to Query 2,you can see that only one column, [Sales Amount], among 129 columns is arequired column. In case you are wondering why ‘Internet Sales’ table has 129columns, you can find the answer in &lt;/span&gt;&lt;a href="http://mdxdax.blogspot.com/2011/03/logic-behind-magic-of-dax-cross-table.html"&gt;&lt;span style="color: blue; font-family: Calibri;"&gt;oneof my earlier posts&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: Calibri;"&gt;.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-left: 0.25in;"&gt;&lt;/div&gt;&lt;pre class="code" style="margin-left: 15px;"&gt;// Query 2&lt;br /&gt;define measure 'Internet Sales'[Total Sales Amount] = Sum([Sales Amount])&lt;br /&gt;evaluate row("x", [Total Sales Amount])&lt;br /&gt;&lt;/pre&gt;&lt;div class="code" style="margin-left: 15px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="code" style="margin-left: 15px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-lR1RYAWIR-U/TyjfRD5H6OI/AAAAAAAAAHI/QV8UvF8dkB4/s1600/RequiredCols.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="56" src="http://2.bp.blogspot.com/-lR1RYAWIR-U/TyjfRD5H6OI/AAAAAAAAAHI/QV8UvF8dkB4/s400/RequiredCols.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;Common Properties of Physical Plan Nodes&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;In a physical plan tree, an iterator operator&amp;nbsp;supplies rows of column values to other nodes.&amp;nbsp;When those rows are fed to&amp;nbsp;a lookup operator, it&amp;nbsp;can&amp;nbsp;return a scalar value from each input row. When the rows are fed to another iterator operator, it&amp;nbsp;can output any number of rows of its own columns for each input row. Therefore, both iterators and lookups share the same input property, &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;LookupCols&lt;/i&gt;&lt;/span&gt;, but they produce different outputs. Let’s use the physical plan tree, shown in Figure 5, captured from Query 1 to illustrate the common properties of physical operators.&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;Here are the properties common to all lookup physical operators (&lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;LookupPhyOp&lt;/i&gt;&lt;/span&gt;):&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"&gt;&lt;span style="mso-list: Ignore;"&gt;·&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;LookupCols&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.25in;"&gt;&lt;span style="font-family: Calibri;"&gt;Columns supplied by an iteratorwhose values are used to calculate a scalar value. In Figure 5, lookupoperators 1 and 2 read their input values from iterator 3; their output valuesare later on used by their parent operator, &lt;i style="mso-bidi-font-style: normal;"&gt;LessThanOrEqualTo&lt;/i&gt;,to calculate a Boolean value.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"&gt;&lt;span style="mso-list: Ignore;"&gt;·&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;Data type&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.25in;"&gt;&lt;span style="font-family: Calibri;"&gt;One of the six data types DAXsupports. Values returned by the operator must be either of this data type orbe the BLANK value.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;Here are the properties common to all iterator physical operators (&lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;IterPhyOp&lt;/i&gt;&lt;/span&gt;):&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"&gt;&lt;span style="mso-list: Ignore;"&gt;·&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;LookupCols&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.25in;"&gt;&lt;span style="font-family: Calibri;"&gt;Identical to the same namedproperty of &lt;i style="mso-bidi-font-style: normal;"&gt;LookupPhyOp&lt;/i&gt;. In Figure 5,iterator 5, which doesn’t have the &lt;i style="mso-bidi-font-style: normal;"&gt;LookupCols&lt;/i&gt;property, hence a pure iterator, supplies column 2 to iterator 4 as its &lt;i style="mso-bidi-font-style: normal;"&gt;LookupCols&lt;/i&gt; property which in turnproduces output column 1.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"&gt;&lt;span style="mso-list: Ignore;"&gt;·&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;IterCols&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.25in;"&gt;&lt;span style="font-family: Calibri;"&gt;Columns output by the iterator.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;It is interesting to learn that a DAX iterator can be a pure iterator, when it only has the &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;IterCols&lt;/i&gt;&lt;/span&gt; &lt;span class="GramE"&gt;property,&lt;/span&gt; or a table-valued function as in T-SQL Apply operator when it has both &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;LookupCols&lt;/i&gt;&lt;/span&gt; and &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;IterCols&lt;/i&gt;&lt;/span&gt; properties, or a pure row checker when it only has the &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;LookupCols&lt;/i&gt;&lt;/span&gt; property. In the last case, the iterator serves the purpose of removing unwanted rows from other iterators.&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-ymfYeNza1W4/Tyjfd5ulEwI/AAAAAAAAAHQ/DzRAwHmvS8c/s1600/PhyOps.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="110" src="http://4.bp.blogspot.com/-ymfYeNza1W4/Tyjfd5ulEwI/AAAAAAAAAHQ/DzRAwHmvS8c/s400/PhyOps.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt; mso-no-proof: yes;"&gt;&lt;/span&gt;&lt;/b&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;For many DAX operators, common properties are all they offer. But some DAX operators output additional properties to provide more information about &lt;span class="GramE"&gt;themselves&lt;/span&gt;. I am not going to go into details about all those operator-specific properties today because it would drag this blog on far too long. I’ll only describe the proprietary properties of one physical operator &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;Spool_IterOnly&lt;/i&gt;&lt;/span&gt; and postpone the discussion of private properties of other operators in future blogs when we get to study individual operators.&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;Special Properties of Physical Operator &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;Spool_IterOnly&lt;/i&gt;&lt;/span&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&amp;lt;&amp;gt;&lt;/i&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;Spool_IterOnly&lt;/i&gt;&lt;/span&gt;&lt;i style="mso-bidi-font-style: normal;"&gt; &lt;/i&gt;is a pure iterator that draws its rows from an in-memory spool which is built through some other means. DAX Formula Engine builds different flavors of in-memory spools, therefore &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;Spool_IterOnly&lt;/i&gt;&lt;/span&gt; along with several other physical operators built from spools put the name of the spool in a pair of angle brackets &amp;lt;&amp;gt; as a part of their names. This is partly caused by the fact that spools are not first class citizens in query plan trees as of SQL Server 2012. As a result, some spool specific properties are added directly to physical operators built on top of the spool. Below is one line I extracted from Figure 5 with &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;Spool_IterOnly&lt;/i&gt;&lt;/span&gt; specific properties highlighted in bold face. They tell us that there are 12 records in the spool and there are 240 key columns (most of which are compressed to 0 bit hence record size is not as wide as it seems) and no value columns.&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;span style="font-size: x-small;"&gt;&lt;span class="SpellE"&gt;Spool_IterOnly&lt;/span&gt;&amp;lt;Spool&amp;gt;: &lt;span class="SpellE"&gt;IterPhyOp&lt;/span&gt; &lt;span class="SpellE"&gt;&lt;span class="GramE"&gt;IterCols&lt;/span&gt;&lt;/span&gt;&lt;span class="GramE"&gt;(&lt;/span&gt;1)('Date'[Month]) &lt;b style="mso-bidi-font-weight: normal;"&gt;#Records=12 #&lt;span class="SpellE"&gt;KeyCols&lt;/span&gt;=240 #&lt;span class="SpellE"&gt;ValueCols&lt;/span&gt;=0&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;Summary&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;Today we studied properties of operator nodes in DAX Query Plan trees. We have learned that some properties are common to all operators of one type and some properties are specific to a particular operator. While I described in details those common properties, I just cited one example of operator specific properties. Now that we have covered the basics of DAX Query Plans, we will be able to explore ways to take advantage of them to investigate performance issues in future posts. When we run into a specific operator of importance, I’ll explain its associated properties at that time.&lt;/div&gt;&lt;div class="WordSection1"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8486191632104654344-2055545184624214162?l=mdxdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdxdax.blogspot.com/feeds/2055545184624214162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mdxdax.blogspot.com/2012/01/dax-query-plan-part-2-operator.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/2055545184624214162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/2055545184624214162'/><link rel='alternate' type='text/html' href='http://mdxdax.blogspot.com/2012/01/dax-query-plan-part-2-operator.html' title='DAX Query Plan, Part 2, Operator Properties'/><author><name>Jeffrey Wang</name><uri>http://www.blogger.com/profile/09745744072887789758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-wi5TXq5wC-U/TyjeFWIBakI/AAAAAAAAAGw/Uub7cN3hiSg/s72-c/ListOfColumns.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8486191632104654344.post-2354503482168242045</id><published>2011-12-30T22:22:00.000-08:00</published><updated>2011-12-31T09:40:46.117-08:00</updated><title type='text'>DAX Query Plan, Part 1, Introduction</title><content type='html'>&lt;div class="WordSection1"&gt;&lt;div class="MsoNormal"&gt;&lt;a href="http://www.microsoft.com/download/en/details.aspx?id=28145"&gt;&lt;span style="color: blue;"&gt;SQL Server 2012 Analysis Services RC0&lt;/span&gt;&lt;/a&gt; introduced a new SQL Server Profiler event class, &lt;b style="mso-bidi-font-weight: normal;"&gt;DAX Query Plan&lt;/b&gt;, under the &lt;b style="mso-bidi-font-weight: normal;"&gt;Query Processing&lt;/b&gt; event category. This is an advanced and rich new event class, but there has been no official document yet. Nonetheless, it has already attracted the attention of some users who are pushing us to release more information as soon as possible. While waiting for an official document to come out, I’ll try to find some spare time to temporarily fill the gap by providing some background information on this event class in a series of blog posts. As always, my goal is to provide accurate information with sufficient technical details. There are plenty of other BI professionals who are eager to help average users to learn this feature through intuitive, practical examples. I’ll be using the tabular model &lt;a href="http://msftdbprodsamples.codeplex.com/releases/view/55330"&gt;&lt;span style="color: blue;"&gt;&lt;span class="SpellE"&gt;AdventureWorks&lt;/span&gt; for SQL Server 2012 RC0&lt;/span&gt;&lt;/a&gt; when I need to demonstrate different aspects of DAX query plans through examples.&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;The &lt;b style="mso-bidi-font-weight: normal;"&gt;DAX Query Plan&lt;/b&gt; event class has four event subclasses:&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;ol&gt;&lt;li&gt;DAX &lt;span class="SpellE"&gt;VertiPaq&lt;/span&gt; Logical Plan&lt;/li&gt;&lt;li&gt;DAX &lt;span class="SpellE"&gt;VertiPaq&lt;/span&gt; Physical Plan&lt;/li&gt;&lt;li&gt;DAX &lt;span class="SpellE"&gt;DirectQuery&lt;/span&gt; &lt;span class="SpellE"&gt;Algebrizer&lt;/span&gt; Tree&lt;/li&gt;&lt;li&gt;DAX &lt;span class="SpellE"&gt;DirectQuery&lt;/span&gt; Logical Plan&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;Trace events of subclasses 1 and 2 are fired when a tabular database is in &lt;span class="SpellE"&gt;VertiPaq&lt;/span&gt; mode. Trace events of subclasses 3 and 4 are fired when a database is in &lt;span class="SpellE"&gt;DirectQuery&lt;/span&gt; mode. Since most tabular databases are likely to run in &lt;span class="SpellE"&gt;VertiPaq&lt;/span&gt; mode, I’ll focus my discussions on the first two types of events.&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;Logical Plans and Physical Plans&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;DAX Formula Engine evaluates a DAX expression in multiple stages and generates several tree data structures along the way, see Figure 1. The new trace event outputs two of the trees to help users investigate logic or performance issues. This is a great leap forward from the dark days of debugging MDX expressions. Logical plan trees show the primitive operations that make up the higher level user functions. The powerful yet sometimes mysterious automatic cross-table filtering becomes explicit in logical plan trees. Properties related to the &lt;span class="SpellE"&gt;sparsity&lt;/span&gt; of a scalar &lt;span class="SpellE"&gt;subtree&lt;/span&gt; tell you why DAX Formula Engine chooses one execution plan over another. If poor performance is caused by the Formula Engine, physical plan trees can help you locate the expensive sub-expressions that caused the problem.&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-GUOIkuzcHa8/Tv6qtOHloeI/AAAAAAAAAFM/23xIDlfZa3Q/s1600/QueryEvalStages.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="171" src="http://1.bp.blogspot.com/-GUOIkuzcHa8/Tv6qtOHloeI/AAAAAAAAAFM/23xIDlfZa3Q/s400/QueryEvalStages.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;v:shapetype coordsize="21600,21600" filled="f" id="_x0000_t75" o:preferrelative="t" o:spt="75" path=" m@4@5 l@4@11@9@11@9@5 xe" stroked="f"&gt;&lt;v:stroke joinstyle="miter"&gt;&lt;/v:stroke&gt;&lt;v:formulas&gt;&lt;v:f eqn="if lineDrawn pixelLineWidth 0 "&gt;&lt;/v:f&gt;&lt;v:f eqn="sum @0 1 0 "&gt;&lt;/v:f&gt;&lt;v:f eqn="sum 0 0 @1 "&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @2 1 2 "&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @3 21600 pixelWidth "&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @3 21600 pixelHeight "&gt;&lt;/v:f&gt;&lt;v:f eqn="sum @0 0 1 "&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @6 1 2 "&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @7 21600 pixelWidth "&gt;&lt;/v:f&gt;&lt;v:f eqn="sum @8 21600 0 "&gt;&lt;/v:f&gt;&lt;v:f eqn="prod @7 21600 pixelHeight "&gt;&lt;/v:f&gt;&lt;v:f eqn="sum @10 21600 0 "&gt;&lt;/v:f&gt;&lt;/v:formulas&gt;&lt;v:path gradientshapeok="t" o:connecttype="rect" o:extrusionok="f"&gt;&lt;/v:path&gt;&lt;o:lock aspectratio="t" v:ext="edit"&gt;&lt;/o:lock&gt;&lt;/v:shapetype&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;Format of the Query Plans&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;Let’s first study the general structure and format common to both types of plan trees. Send the following DAX query to the tabular &lt;span class="SpellE"&gt;AdventureWorks&lt;/span&gt; database:&lt;/div&gt;&lt;pre class="code" style="margin-left: 15px;"&gt;define measure 'Internet Sales'[Total Sales Amount] = Sum([Sales Amount])&lt;br /&gt;evaluate&lt;br /&gt;  filter(&lt;br /&gt;    addcolumns(&lt;br /&gt;      crossjoin(&lt;br /&gt;        values('Date'[Calendar Year]),&lt;br /&gt;        values('Product Category'[Product Category Name])&lt;br /&gt;      ),&lt;br /&gt;      "Total Sales Amount", [Total Sales Amount]&lt;br /&gt;    ),&lt;br /&gt;    not isblank([Total Sales Amount])&lt;br /&gt;  )&lt;br /&gt;&lt;/pre&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;When you execute this query, the logical plan tree and the physical plan tree are shown in Figures 2 and 3 respectively.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-DmW55jX80Tg/Tv6sm3AEg0I/AAAAAAAAAFs/vclA3b24RRs/s1600/LogOpTree.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="73" src="http://1.bp.blogspot.com/-DmW55jX80Tg/Tv6sm3AEg0I/AAAAAAAAAFs/vclA3b24RRs/s640/LogOpTree.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-eYgGILAzEkc/Tv6syf4hg0I/AAAAAAAAAF4/eg6NpkOpm2Y/s1600/PhyOpTree.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="130" src="http://1.bp.blogspot.com/-eYgGILAzEkc/Tv6syf4hg0I/AAAAAAAAAF4/eg6NpkOpm2Y/s640/PhyOpTree.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;As you can see, each plan tree is output as a multi-line text. Each line represents a single operator node in the tree. The hierarchical structure of a tree is maintained by indentation. Child nodes show up indented below their parent nodes. Sibling nodes have the same level of indentation under their parent. Each line begins with the name of the operator followed by a colon and properties of the operator starting with the operator type.&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-wZbMlV67YRI/Tv6s_pGMb-I/AAAAAAAAAGE/tRlf5CqJvaY/s1600/TextLineFormat.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="120" src="http://4.bp.blogspot.com/-wZbMlV67YRI/Tv6s_pGMb-I/AAAAAAAAAGE/tRlf5CqJvaY/s640/TextLineFormat.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;Types of Operators&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;There are two types of logical plan nodes and two types of physical plan nodes as shown in the table below. We’ll spend a lot more time in future posts drilling into the details of various operators and their properties.&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: currentColor; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-yfti-tbllook: 1184;"&gt;&lt;tbody&gt;&lt;tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;"&gt;&lt;td style="border: 1pt solid windowtext; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 159.6pt;" valign="top" width="213"&gt;&lt;div class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;Plan Type&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 159.6pt;" valign="top" width="213"&gt;&lt;div class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;Operator Type&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 368.9pt;" valign="top" width="492"&gt;&lt;div class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;Description&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 1;"&gt;&lt;td rowspan="2" style="border-color: currentColor windowtext windowtext; border-style: none solid solid; border-width: medium 1pt 1pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 159.6pt;" valign="top" width="213"&gt;&lt;div class="MsoNormal"&gt;Logical Plan&lt;/div&gt;&lt;/td&gt;&lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 159.6pt;" valign="top" width="213"&gt;&lt;div class="MsoNormal"&gt;&lt;span class="SpellE"&gt;ScaLogOp&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 368.9pt;" valign="top" width="492"&gt;&lt;div class="MsoNormal"&gt;Scalar Logical Operator&lt;/div&gt;&lt;div class="MsoNormal"&gt;Outputs a scalar value of type numeric, string, Boolean, etc.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 2;"&gt;&lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 159.6pt;" valign="top" width="213"&gt;&lt;div class="MsoNormal"&gt;&lt;span class="SpellE"&gt;RelLogOp&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 368.9pt;" valign="top" width="492"&gt;&lt;div class="MsoNormal"&gt;Relational Logical Operator&lt;/div&gt;&lt;div class="MsoNormal"&gt;Outputs a table of columns and rows.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 3;"&gt;&lt;td rowspan="2" style="border-color: currentColor windowtext windowtext; border-style: none solid solid; border-width: medium 1pt 1pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 159.6pt;" valign="top" width="213"&gt;&lt;div class="MsoNormal"&gt;Physical Plan&lt;/div&gt;&lt;/td&gt;&lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 159.6pt;" valign="top" width="213"&gt;&lt;div class="MsoNormal"&gt;&lt;span class="SpellE"&gt;LookupPhyOp&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 368.9pt;" valign="top" width="492"&gt;&lt;div class="MsoNormal"&gt;Lookup Physical Operator&lt;/div&gt;&lt;div class="MsoNormal"&gt;Given a current row as input, calculates and returns a scalar value.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 4; mso-yfti-lastrow: yes;"&gt;&lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 159.6pt;" valign="top" width="213"&gt;&lt;div class="MsoNormal"&gt;&lt;span class="SpellE"&gt;IterPhyOp&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 368.9pt;" valign="top" width="492"&gt;&lt;div class="MsoNormal"&gt;Iterator Physical Operator&lt;/div&gt;&lt;div class="MsoNormal"&gt;Given a current row as an optional input, returns a sequence of rows.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;Number of Trace Events per Query&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;Each time the DAX Formula Engine is called to evaluate a DAX expression, a pair of DAX Query Plan events are generated. Therefore, a DAX query (Evaluate statement) triggers exactly two events: a logical plan event and a physical plan event. But an MDX query may produce any number of pairs of events depending on how many times the MDX Formula Engine has to call into the DAX Formula Engine. At the time of this writing, DAX Formula Engine cannot call back into MDX Formula Engine, although this may change in the future.&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-SWobIO8XMDg/Tv6tPHe_fOI/AAAAAAAAAGQ/Lu4uPjJO2jc/s1600/DAXEntryPoints.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="287" src="http://2.bp.blogspot.com/-SWobIO8XMDg/Tv6tPHe_fOI/AAAAAAAAAGQ/Lu4uPjJO2jc/s400/DAXEntryPoints.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;Event Trigger Points&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;Ideally, the DAX Formula Engine should generate both the logical plan and the physical plan before any query execution happens so users can capture the plans without being blocked by potentially long-running operations. But this is not the case in the current implementation. Logical plans are built in two stages. The first stage is quick and light-weight, but the second stage may need to execute a portion of the tree therefore potentially expensive. Unfortunately the logical plan event is fired after the second stage is completed, so sometimes users may have to wait for certain time-consuming operations to finish before they can capture the logical plan event. But in most cases, constructing and simplifying a logical plan is a quick process. On the other hand, building a physical plan can often involve expensive operations. Although currently the trace event only shows two types of physical plan nodes: lookup and iterator, there is actually a third type of plan node: spool. A spool plan is when an operator materializes its result in memory by executing its entire &lt;span class="SpellE"&gt;subtree&lt;/span&gt;. A physical plan tree may contain many nodes built from spools, each of which requires partial execution of a &lt;span class="SpellE"&gt;subtree&lt;/span&gt; before the entire physical plan tree is fully constructed. In particular, all leaf level nodes which require fetching data from the VertiPaq Engine currently always build&amp;nbsp;spools to store VertiPaq results, therefore, users can see the physical plan event only after all VertiPaq queries have completed.&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-UfUf_ctThLI/Tv9IxVAa-sI/AAAAAAAAAGo/O-CUYdOvLlw/s1600/TriggerPoints.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://4.bp.blogspot.com/-UfUf_ctThLI/Tv9IxVAa-sI/AAAAAAAAAGo/O-CUYdOvLlw/s640/TriggerPoints.png" width="411" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;The new &lt;b style="mso-bidi-font-weight: normal;"&gt;DAX Query Plan&lt;/b&gt; trace event can assist you in writing efficient DAX expressions and troubleshooting problematic DAX behavior. How you use them is up to you, but first you need to understand the information contained within the plans and how to interpret it. Today we have gone over the basics such as types of plans, format of text, types of plan nodes, and when and how frequently the events are fired. Next time we are going one step further to examine the various properties of plan nodes.&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8486191632104654344-2354503482168242045?l=mdxdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdxdax.blogspot.com/feeds/2354503482168242045/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mdxdax.blogspot.com/2011/12/dax-query-plan-part-1-introduction.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/2354503482168242045'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/2354503482168242045'/><link rel='alternate' type='text/html' href='http://mdxdax.blogspot.com/2011/12/dax-query-plan-part-1-introduction.html' title='DAX Query Plan, Part 1, Introduction'/><author><name>Jeffrey Wang</name><uri>http://www.blogger.com/profile/09745744072887789758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-GUOIkuzcHa8/Tv6qtOHloeI/AAAAAAAAAFM/23xIDlfZa3Q/s72-c/QueryEvalStages.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8486191632104654344.post-7412297749783367560</id><published>2011-11-15T17:08:00.001-08:00</published><updated>2011-11-15T17:41:40.106-08:00</updated><title type='text'>Avoid Pitfalls of Fact Data Prefetching</title><content type='html'>&lt;style&gt;v\:* {behavior:url(#default#VML);}o\:* {behavior:url(#default#VML);}w\:* {behavior:url(#default#VML);}.shape {behavior:url(#default#VML);}&lt;/style&gt;&lt;style&gt;&lt;!-- /* Font Definitions */ @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;}@font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:-536870145 1107305727 0 0 415 0;}@font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-520092929 1073786111 9 0 415 0;}@font-face {font-family:Tahoma; panose-1:2 11 6 4 3 5 4 4 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-520081665 -1073717157 41 0 66047 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin-top:0in; margin-right:0in; margin-bottom:10.0pt; margin-left:0in; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}p.MsoAcetate, li.MsoAcetate, div.MsoAcetate {mso-style-noshow:yes; mso-style-priority:99; mso-style-link:"Balloon Text Char"; margin:0in; margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:8.0pt; font-family:"Tahoma","sans-serif"; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin;}span.BalloonTextChar {mso-style-name:"Balloon Text Char"; mso-style-noshow:yes; mso-style-priority:99; mso-style-unhide:no; mso-style-locked:yes; mso-style-link:"Balloon Text"; mso-ansi-font-size:8.0pt; mso-bidi-font-size:8.0pt; font-family:"Tahoma","sans-serif"; mso-ascii-font-family:Tahoma; mso-hansi-font-family:Tahoma; mso-bidi-font-family:Tahoma;}span.SpellE {mso-style-name:""; mso-spl-e:yes;}span.GramE {mso-style-name:""; mso-gram-e:yes;}.MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:Calibri; mso-fareast-theme-font:minor-latin; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;}.MsoPapDefault {mso-style-type:export-only; margin-bottom:10.0pt; line-height:115%;}@page WordSection1 {size:8.5in 11.0in; margin:1.0in 1.0in 1.0in 1.0in; mso-header-margin:.5in; mso-footer-margin:.5in; mso-paper-source:0;}div.WordSection1 {page:WordSection1;}--&gt;&lt;/style&gt;As mentioned in Chris Webb’s article &lt;i style="mso-bidi-font-style: normal;"&gt;&lt;a href="http://www.packtpub.com/article/query-performance-tuning-microsoft-analysis-services-part1"&gt;&lt;span style="color: blue;"&gt;Query Performance Tuning in Microsoft Analysis Services&lt;/span&gt;&lt;/a&gt;&lt;/i&gt; and SQL Server CAT team’s white paper &lt;i style="mso-bidi-font-style: normal;"&gt;&lt;a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;amp;id=661"&gt;&lt;span style="color: blue;"&gt;SQLServer Best Practices Article: Identifying and Resolving MDX Query PerformanceBottlenecks in SQL Server 2005 Analysis Services&lt;/span&gt;&lt;/a&gt;&lt;/i&gt;,MDX Formula Engine (FE) may request more data from the Storage Engine (SE)upfront so that following SE queries can be answered directly from the SE cache.In order to retrieve the right amount of data, FE uses some clever heuristicsto construct the prefetch query. While the underlying design delivers greatperformance most of the time, sometimes the resulting query prefetches too muchdata. In this blog post I am going to show you a pathological case where aprefetch query seems to completely ignore the slices in the original MDX querythereby scan all partitions instead of just the needed ones. I will explain whyit happens so you understand what’s going on in the engine if you ever run intosuch cases and deal with it accordingly.&lt;br /&gt;&lt;div class="WordSection1"&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;To illustrate the problem, I am going to run a series of MDXqueries against the &lt;span class="SpellE"&gt;AdventureWorks&lt;/span&gt; sample databasefor Microsoft SQL Server 2008R2. In between queries, I send &lt;a href="http://geekswithblogs.net/darrengosbell/archive/2007/08/30/SSAS-Query-Performance-Tuning-Whitepaper.aspx"&gt;&lt;span style="color: blue;"&gt;ClearCache commands&lt;/span&gt;&lt;/a&gt;to eliminate inter-query interference. For each MDX query, we are going toobserve the sequence of SE queries through the &lt;b style="mso-bidi-font-weight: normal;"&gt;Query Subcube Verbose&lt;/b&gt; profiler trace events. Instead of showing thecomplete output of &lt;b style="mso-bidi-font-weight: normal;"&gt;Query Subcube Verbose&lt;/b&gt;events, I am going to extract only those attributes in the [Date] dimensionwhich are relevant to our discussion. As well known in the MDX community, AnalysisServices engine internally uses subcubes to represent queries, therefore I willuse the terms query and subcube interchangeably throughout the post.&lt;/div&gt;&lt;div class="MsoNormal"&gt;Now, let’s run our first MDX query to retrieve the values ofmeasure [Internet Sales Amount] for all days in January 2007.&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;Query 1:&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;// January2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;select&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; [Internet Sales Amount] on 0,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;head(&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;descendants([Date].[Calendar].[Calendar Year].&amp;amp;[2007],[Date].[Calendar].[Date]), 31) on 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;from&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; [Adventure Works]&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;Since measure [Internet Sales Amount] is defined as ameasure expression, there are three &lt;b style="mso-bidi-font-weight: normal;"&gt;QuerySubcube Verbose&lt;/b&gt; events, one for the [Exchange Rates] measure group, two forthe [Internet Sales] measure group, although only one of them hits thepartitions, the other is just an artifact of measure expression evaluation.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-tu8Xkl7uEjs/TsMNZQXaMYI/AAAAAAAAAEM/V5iPSnYNwz8/s1600/Q1ProfilerTrace.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="92" src="http://4.bp.blogspot.com/-tu8Xkl7uEjs/TsMNZQXaMYI/AAAAAAAAAEM/V5iPSnYNwz8/s640/Q1ProfilerTrace.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;v:shapetype coordsize="21600,21600" filled="f" id="_x0000_t75" o:preferrelative="t" o:spt="75" path="m@4@5l@4@11@9@11@9@5xe" stroked="f"&gt; &lt;v:stroke joinstyle="miter"&gt; &lt;v:formulas&gt;  &lt;v:f eqn="if lineDrawn pixelLineWidth 0"&gt;  &lt;v:f eqn="sum @0 1 0"&gt;  &lt;v:f eqn="sum 0 0 @1"&gt;  &lt;v:f eqn="prod @2 1 2"&gt;  &lt;v:f eqn="prod @3 21600 pixelWidth"&gt;  &lt;v:f eqn="prod @3 21600 pixelHeight"&gt;  &lt;v:f eqn="sum @0 0 1"&gt;  &lt;v:f eqn="prod @6 1 2"&gt;  &lt;v:f eqn="prod @7 21600 pixelWidth"&gt;  &lt;v:f eqn="sum @8 21600 0"&gt;  &lt;v:f eqn="prod @7 21600 pixelHeight"&gt;  &lt;v:f eqn="sum @10 21600 0"&gt; &lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:formulas&gt; &lt;v:path gradientshapeok="t" o:connecttype="rect" o:extrusionok="f"&gt; &lt;o:lock aspectratio="t" v:ext="edit"&gt;&lt;/o:lock&gt;&lt;/v:path&gt;&lt;/v:stroke&gt;&lt;/v:shapetype&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;Here are the attributes corresponding to levels in the[Calendar] hierarchy extracted from the trace events:&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Dimension 7 [Date] (0 * 8 0 6 0 0 0 0 00 20 4 0 0 0 0 0 0 0 0)&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Date]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Quarter]&lt;span class="GramE"&gt;:[&lt;/span&gt;Q1CY 2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Semester]&lt;span class="GramE"&gt;:[&lt;/span&gt;H1CY 2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Month Name]&lt;span class="GramE"&gt;:[&lt;/span&gt;January2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Year]&lt;span class="GramE"&gt;:[&lt;/span&gt;CY2007]&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;The SE query asks for all days in January 2007, which matchexactly the days listed on Axis 1 of the MDX query, with the added benefit ofnot listing each day individually. There is no prefetch query in this casewhich makes sense as the original query is asking for all days in January 2007that matches exactly the SE query.&lt;/div&gt;&lt;div class="MsoNormal"&gt;Now let’s add one more day to the query.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;Query 2:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;// January2007 + February 1 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;select&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; [Internet Sales Amount] on 0,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;head(&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;descendants([Date].[Calendar].[Calendar Year].&amp;amp;[2007],[Date].[Calendar].[Date]), 32) on 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;from&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; [Adventure Works]&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;From thecaptured profiler trace below&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-qO0pzqE2qAw/TsMNaYWXN9I/AAAAAAAAAEU/dfEwQSNe0TY/s1600/Q2ProfilerTrace.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="122" src="http://2.bp.blogspot.com/-qO0pzqE2qAw/TsMNaYWXN9I/AAAAAAAAAEU/dfEwQSNe0TY/s640/Q2ProfilerTrace.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;You canextract the following information form the three queries sent to the [InternetSales] measure group:&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Non-cache data&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Dimension 7 [Date] (0 * 8 0 6 0 0 0 0 00 20 4 0 0 0 0 0 0 0 0)&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Date]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Quarter]&lt;span class="GramE"&gt;:[&lt;/span&gt;Q1CY 2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Semester]&lt;span class="GramE"&gt;:[&lt;/span&gt;H1CY 2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Month Name]&lt;span class="GramE"&gt;:[&lt;/span&gt;January2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Year]&lt;span class="GramE"&gt;:[&lt;/span&gt;CY2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Non-cache data&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Dimension 7 [Date] (0 * 8 0 6 0 0 0 0 00 21 4 0 0 0 0 0 0 0 0)&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Date]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Quarter]&lt;span class="GramE"&gt;:[&lt;/span&gt;Q1CY 2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Semester]&lt;span class="GramE"&gt;:[&lt;/span&gt;H1CY 2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Month Name]&lt;span class="GramE"&gt;:[&lt;/span&gt;February2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Year]&lt;span class="GramE"&gt;:[&lt;/span&gt;CY2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Cache data&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Dimension 7 [Date] (0 582 8 0 6 0 0 0 00 0 21 4 0 0 0 0 0 0 0 0)&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Date]&lt;span class="GramE"&gt;:[&lt;/span&gt;February1, 2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Quarter]&lt;span class="GramE"&gt;:[&lt;/span&gt;Q1CY 2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Semester]&lt;span class="GramE"&gt;:[&lt;/span&gt;H1CY 2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Month Name]&lt;span class="GramE"&gt;:[&lt;/span&gt;February2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Year]&lt;span class="GramE"&gt;:[&lt;/span&gt;CY2007]&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;Again there is no prefetch query for January 2007 but FEdoes prefetch all days in February 2007 first before getting the value ofFebruary 1, 2007 from cached data.&lt;/div&gt;&lt;div class="MsoNormal"&gt;Now let’s add one more day again to the query.&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;Query 3:&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;// January2007 + February 1 2007 + February 2 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;select&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; [Internet Sales Amount] on 0,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;head(&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;descendants([Date].[Calendar].[Calendar Year].&amp;amp;[2007],[Date].[Calendar].[Date]), 33) on 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;from&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; [Adventure Works]&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;Below is the profiler trace events and relevant informationextracted from them:&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-uIj35K6M2kc/TsMNboVr00I/AAAAAAAAAEc/bEN2qnfQMyo/s1600/Q3ProfilerTrace.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="156" src="http://4.bp.blogspot.com/-uIj35K6M2kc/TsMNboVr00I/AAAAAAAAAEc/bEN2qnfQMyo/s640/Q3ProfilerTrace.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal"&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Non-cache data:&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Dimension 7 [Date] (0 * * 0 * 0 0 0 0 00 * * 0 0 0 0 0 0 0 0)&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Date]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Quarter]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Semester]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Month Name]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Year]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Cache data:&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Dimension 7 [Date] (0 * 8 0 6 0 0 0 0 00 20 4 0 0 0 0 0 0 0 0)&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Date]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Quarter]&lt;span class="GramE"&gt;:[&lt;/span&gt;Q1CY 2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Semester]&lt;span class="GramE"&gt;:[&lt;/span&gt;H1CY 2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Month Name]&lt;span class="GramE"&gt;:[&lt;/span&gt;January2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Year]&lt;span class="GramE"&gt;:[&lt;/span&gt;CY2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Cache data:&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Dimension 7 [Date] (0 + * 0 * 0 0 0 0 00 * * 0 0 0 0 0 0 0 0)&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Date]:+&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Quarter]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Semester]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Month Name]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Year]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;One &lt;span class="SpellE"&gt;&lt;span class="GramE"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;EventSubclass&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="GramE"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt; &lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;=&lt;/b&gt;&lt;/span&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt; Non-Cache data&lt;/b&gt; query prefetches fact data into SE cache which isused to answer the subsequent two SE queries shown as &lt;span class="SpellE"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;EventSubclass&lt;/b&gt;&lt;/span&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;=Cache data&lt;/b&gt;, one for all days in January 2007, the other for the first twodays of February 2007. But why did the prefetch query ask for data for alldates? Why did we lose all slices in the [Date] dimension? This is really badas it would have caused all partitions to be scanned. The answer lies in theimprecise nature of the algorithm used to construct the prefetch subcube.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;In order tobuild the prefetch SE subcube, FE keeps track of all relevant MDX sets in a stack-likedata structure called Sonar registry. Later on each MDX set in the Sonarregistry is used to build a collection of Sonar subcubes. &lt;span class="SpellE"&gt;Perfmon&lt;/span&gt;counter &lt;b style="mso-bidi-font-weight: normal;"&gt;MDX\Total Sonar subcubes&lt;/b&gt;displays the total number of Sonar subcubes generated inside FE.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Aw9ntu4dzsM/TsMNd5_lxUI/AAAAAAAAAEs/K4UGrorMjIk/s1600/Perfmon.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="38" src="http://1.bp.blogspot.com/-Aw9ntu4dzsM/TsMNd5_lxUI/AAAAAAAAAEs/K4UGrorMjIk/s640/Perfmon.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;By default,the conversion from an MDX set to its collection of Sonar subcubes is not aprecise process. The resulting Sonar subcubes will cover the original MDX setbut may include additional members on some attributes. The &lt;b style="mso-bidi-font-weight: normal;"&gt;Cache Ratio&lt;/b&gt; connection string property controls how a Sonar subcubeattribute is expanded to include more members than what the original setcontains. The actual algorithm is very complex. I am only going to show here agreatly simplified version that illustrates the main idea of the algorithm.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;Algorithm 1: Build Sonar subcubes from anMDX set&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;Input: anMDX set &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt;, for simplicity, assume &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt; is single-grained&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;For each hierarchy&lt;i style="mso-bidi-font-style: normal;"&gt;H&lt;/i&gt; in &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Since &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt; is single-grained, let &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;L&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;s&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; &lt;/span&gt;be thelevel of &lt;i style="mso-bidi-font-style: normal;"&gt;H&lt;/i&gt; where members of &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt; reside&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;For each level &lt;i style="mso-bidi-font-style: normal;"&gt;L&lt;/i&gt; in &lt;i style="mso-bidi-font-style: normal;"&gt;H&lt;/i&gt; starting from thetopmost level down to &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;L&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;s&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1in;"&gt;Identify all members on &lt;i style="mso-bidi-font-style: normal;"&gt;L&lt;/i&gt; with good coverage of &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1in;"&gt;A member &lt;i style="mso-bidi-font-style: normal;"&gt;M&lt;/i&gt; has good coverage of &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt;if the ratio of the number of its descendants in &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt; to the number of all its descendants on level &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;L&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;s&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; &lt;/span&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;is greaterthan or equal to&lt;/span&gt; the Cache Ratio&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1in;"&gt;Add &lt;i style="mso-bidi-font-style: normal;"&gt;M&lt;/i&gt; to the list of slicers on level &lt;i style="mso-bidi-font-style: normal;"&gt;L&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;For each level with a nonempty list ofslicers&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1in;"&gt;Create a Sonar subcube with granularitieson attributes corresponding to the levels of &lt;i style="mso-bidi-font-style: normal;"&gt;H&lt;/i&gt; from the topmost level down to &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;L&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;s&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1in;"&gt;Apply the list of slicers to thesubcube&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;Output: thecollection of generated Sonar subcubes&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;First, apply&lt;b style="mso-bidi-font-weight: normal;"&gt;Algorithm 1&lt;/b&gt; to the [Calendar] set in&lt;b style="mso-bidi-font-weight: normal;"&gt;Query 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;head(&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;descendants([Date].[Calendar].[CalendarYear].&amp;amp;[2007], [Date].[Calendar].[Date]), 31)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span class="GramE"&gt;you&lt;/span&gt; get the following sequence of slices encoded in internaldata IDs and eventually FE finds a single good cover slice on the month level.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Sonar [Calendar] [1 * * * * *] ratio:31/1188&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 * * * *] ratio: 31/365&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 6 * * *] ratio: 31/181&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 6 8 * *] ratio: 31/90&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 6 8 20 *] ratio: 31/31 &lt;span style="font-family: Wingdings; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-char-type: symbol; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin; mso-symbol-font-family: Wingdings;"&gt;&lt;span style="mso-char-type: symbol; mso-symbol-font-family: Wingdings;"&gt;ß&lt;/span&gt;&lt;/span&gt; good cover&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;Theresulting Sonar subcube is&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;SonarSubcube 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: currentColor; margin-left: 0.5in; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-yfti-tbllook: 1184;"&gt; &lt;tbody&gt;&lt;tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;"&gt;  &lt;td style="border: 1pt solid windowtext; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.95in;" valign="top" width="91"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Year&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1.25in;" valign="top" width="120"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Semester&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Quarter&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 67.5pt;" valign="top" width="90"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Month Name&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.5in;" valign="top" width="48"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Date&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr style="mso-yfti-irow: 1; mso-yfti-lastrow: yes;"&gt;  &lt;td style="border-color: currentColor windowtext windowtext; border-style: none solid solid; border-width: medium 1pt 1pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.95in;" valign="top" width="91"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1.25in;" valign="top" width="120"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;H1 CY 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Q1 CY 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 67.5pt;" valign="top" width="90"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;January 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.5in;" valign="top" width="48"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;*&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;Here and inthe following I only show the important attributes in the Sonar subcube whichcorrespond to levels of the [Calendar] hierarchy. Next, apply &lt;b style="mso-bidi-font-weight: normal;"&gt;Algorithm 1&lt;/b&gt; to the [Calendar] set in &lt;b style="mso-bidi-font-weight: normal;"&gt;Query 2&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;head(&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;descendants([Date].[Calendar].[CalendarYear].&amp;amp;[2007], [Date].[Calendar].[Date]), 32)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;FE finds twogood cover slices, one on the month level and the other on the date level.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Sonar [Calendar] [1 * * * * *] ratio:32/1188&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 * * * *] ratio: 32/365&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 6 * * *] ratio: 32/181&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 6 8 * *] ratio: 32/90&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 6 8 20 *] ratio: 31/31 &lt;span style="font-family: Wingdings; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-char-type: symbol; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin; mso-symbol-font-family: Wingdings;"&gt;&lt;span style="mso-char-type: symbol; mso-symbol-font-family: Wingdings;"&gt;ß&lt;/span&gt;&lt;/span&gt; good cover&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 6 8 21 *] ratio: 1/28&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 6 8 21 582] ratio: 1/1 &lt;span style="font-family: Wingdings; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-char-type: symbol; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin; mso-symbol-font-family: Wingdings;"&gt;&lt;span style="mso-char-type: symbol; mso-symbol-font-family: Wingdings;"&gt;ß&lt;/span&gt;&lt;/span&gt; good cover&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;The twoSonar subcubes created are:&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;SonarSubcube 2.1&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: currentColor; margin-left: 0.5in; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-yfti-tbllook: 1184;"&gt; &lt;tbody&gt;&lt;tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;"&gt;  &lt;td style="border: 1pt solid windowtext; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.95in;" valign="top" width="91"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Year&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1.25in;" valign="top" width="120"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Semester&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Quarter&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 67.5pt;" valign="top" width="90"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Month Name&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.5in;" valign="top" width="48"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Date&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr style="mso-yfti-irow: 1; mso-yfti-lastrow: yes;"&gt;  &lt;td style="border-color: currentColor windowtext windowtext; border-style: none solid solid; border-width: medium 1pt 1pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.95in;" valign="top" width="91"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1.25in;" valign="top" width="120"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;H1 CY 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Q1 CY 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 67.5pt;" valign="top" width="90"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;January 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.5in;" valign="top" width="48"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;*&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;SonarSubcube 2.2&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: currentColor; margin-left: 0.5in; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-yfti-tbllook: 1184;"&gt; &lt;tbody&gt;&lt;tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;"&gt;  &lt;td style="border: 1pt solid windowtext; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.95in;" valign="top" width="91"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Year&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1.25in;" valign="top" width="120"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Semester&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Quarter&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1in;" valign="top" width="96"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Month Name&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 81pt;" valign="top" width="108"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Date&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr style="mso-yfti-irow: 1; mso-yfti-lastrow: yes;"&gt;  &lt;td style="border-color: currentColor windowtext windowtext; border-style: none solid solid; border-width: medium 1pt 1pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.95in;" valign="top" width="91"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1.25in;" valign="top" width="120"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;H1 CY 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Q1 CY 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1in;" valign="top" width="96"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;February  2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 81pt;" valign="top" width="108"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;February 1,  2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;Finally,apply &lt;b style="mso-bidi-font-weight: normal;"&gt;Algorithm 1&lt;/b&gt; to the [Calendar]set in &lt;b style="mso-bidi-font-weight: normal;"&gt;Query 3&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;head(&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;descendants([Date].[Calendar].[CalendarYear].&amp;amp;[2007], [Date].[Calendar].[Date]), 33)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;FE findsthree good cover slices, one on the month level and two on the date level.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Sonar [Calendar] [1 * * * * *] ratio:33/1188&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 * * * *] ratio: 33/365&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 6 * * *] ratio: 33/181&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 6 8 * *] ratio: 33/90&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 6 8 20 *] ratio: 31/31 &lt;span style="font-family: Wingdings; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-char-type: symbol; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin; mso-symbol-font-family: Wingdings;"&gt;&lt;span style="mso-char-type: symbol; mso-symbol-font-family: Wingdings;"&gt;ß&lt;/span&gt;&lt;/span&gt; good cover&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 6 8 21 *] ratio: 2/28&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 6 8 21 582] ratio: 1/1 &lt;span style="font-family: Wingdings; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-char-type: symbol; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin; mso-symbol-font-family: Wingdings;"&gt;&lt;span style="mso-char-type: symbol; mso-symbol-font-family: Wingdings;"&gt;ß&lt;/span&gt;&lt;/span&gt; good cover&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;Sonar [Calendar] [1 4 6 8 21 583] ratio: 1/1 &lt;span style="font-family: Wingdings; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-char-type: symbol; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin; mso-symbol-font-family: Wingdings;"&gt;&lt;span style="mso-char-type: symbol; mso-symbol-font-family: Wingdings;"&gt;ß&lt;/span&gt;&lt;/span&gt; good cover&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;Again, FEcreated two Sonar subcubes.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;SonarSubcube 3.1&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: currentColor; margin-left: 0.5in; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-yfti-tbllook: 1184;"&gt; &lt;tbody&gt;&lt;tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;"&gt;  &lt;td style="border: 1pt solid windowtext; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.95in;" valign="top" width="91"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Year&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1.25in;" valign="top" width="120"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Semester&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Quarter&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 67.5pt;" valign="top" width="90"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Month Name&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.5in;" valign="top" width="48"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Date&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr style="mso-yfti-irow: 1; mso-yfti-lastrow: yes;"&gt;  &lt;td style="border-color: currentColor windowtext windowtext; border-style: none solid solid; border-width: medium 1pt 1pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.95in;" valign="top" width="91"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1.25in;" valign="top" width="120"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;H1 CY 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Q1 CY 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 67.5pt;" valign="top" width="90"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;January 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.5in;" valign="top" width="48"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;*&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;SonarSubcube 3.2&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: currentColor; margin-left: 0.5in; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-yfti-tbllook: 1184;"&gt; &lt;tbody&gt;&lt;tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;"&gt;  &lt;td style="border: 1pt solid windowtext; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.95in;" valign="top" width="91"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Year&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1.25in;" valign="top" width="120"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar Semester&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Quarter&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1in;" valign="top" width="96"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Month Name&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 31.5pt;" valign="top" width="42"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Date&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr style="mso-yfti-irow: 1; mso-yfti-lastrow: yes;"&gt;  &lt;td style="border-color: currentColor windowtext windowtext; border-style: none solid solid; border-width: medium 1pt 1pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.95in;" valign="top" width="91"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;*&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1.25in;" valign="top" width="120"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;*&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;*&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1in;" valign="top" width="96"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;*&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 31.5pt;" valign="top" width="42"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;+&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;Note that &lt;b style="mso-bidi-font-weight: normal;"&gt;Sonar Subcube 2.2&lt;/b&gt; retains slices on alllevels of the [Calendar] hierarchy while &lt;b style="mso-bidi-font-weight: normal;"&gt;SonarSubcube 3.2&lt;/b&gt; only has a slice on the lowest level of the [Calendar]hierarchy. This is an artifact of the current implementation. When multiplecovering members of a hierarchy are added to a Sonar subcube, only a singleslice is created at the lowest level of the hierarchy.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;FE usesSonar subcubes in several different places, including constructing a largerevaluation node when FE is executing in cell-by-cell mode. In the simple casewhere an MDX query can be answered directly from SE, Sonar subcubes are used toconstruct SE queries.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;Algorithm 2: Evaluate cell values&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;Input: acell iterator and the current Sonar registry&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;For eachcell &lt;i style="mso-bidi-font-style: normal;"&gt;C&lt;o:p&gt;&lt;/o:p&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Find the Sonar subcube &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt; that contains &lt;i style="mso-bidi-font-style: normal;"&gt;C&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Build an evaluation node &lt;i style="mso-bidi-font-style: normal;"&gt;E &lt;/i&gt;for &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Execute &lt;i style="mso-bidi-font-style: normal;"&gt;E&lt;/i&gt;. In the simplest case, create SE subcube &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;sub&gt;SE&lt;/sub&gt;&lt;/i&gt; from &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt; andsend &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;sub&gt;SE&lt;/sub&gt;&lt;/i&gt; to SE.&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Lookup value of &lt;i style="mso-bidi-font-style: normal;"&gt;C&lt;/i&gt; from cached result in &lt;i style="mso-bidi-font-style: normal;"&gt;E&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;Output: cellvalues&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;Anotherusage of Sonar subcubes is to build a prefetch subcube from a given SE querysubcube. The full algorithm is again very complex with exceptions and specialhandling of arbitrary shapes or unary operators, etc. Here I include asimplified version to illustrate the essence of the algorithm:&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;Algorithm 3: Build a prefetch subcube for aquery subcube&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;Input: a SE querysubcube &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;query&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; and the currentSonar registry&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;Initializethe prefetch subcube &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;prefetch&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt; asa clone of &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;query&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;,&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span class="GramE"&gt;For each Sonar&lt;/span&gt; subcube &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;sonar&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; in theSonar registry&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;For each attribute &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;A&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;prefetch&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;in &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;prefetch&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1in;"&gt;Find the corresponding attribute &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;A&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;sonar&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt; in &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;sonar&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1in;"&gt;Skip &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;A&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;sonar&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; if it isnot a granularity &lt;span class="GramE"&gt;attribute&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1in;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;If &lt;/span&gt;&lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;A&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;prefetch&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; is agranularity attribute&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1.5in;"&gt;If the slice of &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;A&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;sonar&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; is asuperset of the slice of &lt;/span&gt;&lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;A&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;prefetch&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 2in;"&gt;Copy the slice of &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;A&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;sonar&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; to &lt;/span&gt;&lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;A&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;prefetch&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1in;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;Else&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1.5in;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;If the slice of &lt;/span&gt;&lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;A&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;sonar&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; includes all members&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 2in;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;Make &lt;/span&gt;&lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;A&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;prefetch&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; &lt;span class="GramE"&gt;a granularity attribute&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 2in;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;Output: &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;S&lt;/span&gt;&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;prefetch&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt; if it is different from &lt;span class="SpellE"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;S&lt;/span&gt;&lt;/i&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;&lt;sub&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;query&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;In &lt;b style="mso-bidi-font-weight: normal;"&gt;Query 1&lt;/b&gt;, &lt;b style="mso-bidi-font-weight: normal;"&gt;Sonar Subcube 1&lt;/b&gt; is equivalent to the SE query subcube therefore noprefetch subcube is needed. In &lt;b style="mso-bidi-font-weight: normal;"&gt;Query 2&lt;/b&gt;,the first SE query subcube matches &lt;b style="mso-bidi-font-weight: normal;"&gt;SonarSubcube 2.1&lt;/b&gt; so again no prefetch subcube is needed. But the second SE querywould copy the * from [Date] in &lt;b style="mso-bidi-font-weight: normal;"&gt;SonarSubcube 2.1 &lt;/b&gt;therefore produce a prefetch subcube that fetches all days inFebruary. The * in &lt;b style="mso-bidi-font-weight: normal;"&gt;Sonar Subcube 2.1 &lt;/b&gt;reallymeans all days in January 2007 but &lt;b style="mso-bidi-font-weight: normal;"&gt;Algorithm3&lt;/b&gt; treats each attribute independently and is oblivious to the fact that[Date]:* is cross-filtered by slices on other attributes. But the end result ofprefetching all days in February 2007 isn’t too bad.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;PrefetchSubcube 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: currentColor; margin-left: 0.5in; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-yfti-tbllook: 1184;"&gt; &lt;tbody&gt;&lt;tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;"&gt;  &lt;td style="border: 1pt solid windowtext; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.95in;" valign="top" width="91"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Year&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1.25in;" valign="top" width="120"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Semester&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Quarter&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1in;" valign="top" width="96"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Month Name&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 31.5pt;" valign="top" width="42"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Date&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr style="mso-yfti-irow: 1; mso-yfti-lastrow: yes;"&gt;  &lt;td style="border-color: currentColor windowtext windowtext; border-style: none solid solid; border-width: medium 1pt 1pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.95in;" valign="top" width="91"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1.25in;" valign="top" width="120"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;H1 CY 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Q1 CY 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1in;" valign="top" width="96"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;February  2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 31.5pt;" valign="top" width="42"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;*&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;But when wecome to &lt;b style="mso-bidi-font-weight: normal;"&gt;Query 3&lt;/b&gt;, there is a * oneach attribute from either &lt;b style="mso-bidi-font-weight: normal;"&gt;Sonar Subcube3.1&lt;/b&gt; or &lt;b style="mso-bidi-font-weight: normal;"&gt;Sonar Subcube 3.2&lt;/b&gt;, we endup with a prefetch subcube that has * on all its attributes.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;PrefetchSubcube 2&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: currentColor; margin-left: 0.5in; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-yfti-tbllook: 1184;"&gt; &lt;tbody&gt;&lt;tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;"&gt;  &lt;td style="border: 1pt solid windowtext; mso-border-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.95in;" valign="top" width="91"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Year&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1.25in;" valign="top" width="120"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Semester&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Calendar  Quarter&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1in;" valign="top" width="96"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Month Name&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: windowtext windowtext windowtext currentColor; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 31.5pt;" valign="top" width="42"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;Date&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;tr style="mso-yfti-irow: 1; mso-yfti-lastrow: yes;"&gt;  &lt;td style="border-color: currentColor windowtext windowtext; border-style: none solid solid; border-width: medium 1pt 1pt; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 0.95in;" valign="top" width="91"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;*&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1.25in;" valign="top" width="120"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;*&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;*&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 1in;" valign="top" width="96"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;*&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;  &lt;td style="border-color: currentColor windowtext windowtext currentColor; border-style: none solid solid none; border-width: medium 1pt 1pt medium; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding: 0in 5.4pt; width: 31.5pt;" valign="top" width="42"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; mso-bidi-font-size: 11.0pt;"&gt;*&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt; &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;Nowadays weare seeing more and more implementation of systems with multiple terabytes ofdata in Analysis Services. The above example of overly aggressive prefetchingof fact data is unacceptable in such environments. You can disable prefetchingaltogether by setting connection string property &lt;b style="mso-bidi-font-weight: normal;"&gt;Disable Prefetch Facts&lt;/b&gt;=true or you can play with the &lt;b style="mso-bidi-font-weight: normal;"&gt;Cache Ratio&lt;/b&gt; connection string property toinfluence the Sonar subcubes generated by FE. But either approach is likely tohave negative performance impact that would require a lot of testing to confirmtheir overall benefit against a certain query set. If you can control the typesof queries in your deployment, it is better to replace queries that fall intothis pitfall with ones that produce good Sonar subcubes in the default settings.Using our example, since we know that there are 90 days in the first quarterand the default &lt;b style="mso-bidi-font-weight: normal;"&gt;Cache Ratio&lt;/b&gt; is 0.5, wecan simply ask for 45 days instead of 33 days to produce a single good cover atquarter level.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;Query 4:&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;// January2007 + February 1-14 2007&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;select&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; [Internet Sales Amount] on 0,&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;head(&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;descendants([Date].[Calendar].[Calendar Year].&amp;amp;[2007],[Date].[Calendar].[Date]), 45) on 1&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;span class="GramE"&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;from&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 10pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt; [Adventure Works]&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;a href="http://3.bp.blogspot.com/-aN0-_QxVwBQ/TsMNc--03OI/AAAAAAAAAEk/rYGCmNGV1wk/s1600/Q4ProfilerTrace.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="96" src="http://3.bp.blogspot.com/-aN0-_QxVwBQ/TsMNc--03OI/AAAAAAAAAEk/rYGCmNGV1wk/s640/Q4ProfilerTrace.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;The capturedprofiler trace confirmed our conjecture as it shows a single SE query to the[Internet Sales] measure group to retrieve all days in the first quarter of2007.&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;Dimension 7 [Date] (0 * 8 0 6 0 0 0 0 00 * 4 0 0 0 0 0 0 0 0)&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Date]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Quarter]&lt;span class="GramE"&gt;:[&lt;/span&gt;Q1CY 2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Semester]&lt;span class="GramE"&gt;:[&lt;/span&gt;H1CY 2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Month Name]:*&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;[Calendar Year]&lt;span class="GramE"&gt;:[&lt;/span&gt;CY2007]&lt;/div&gt;&lt;div class="MsoNormal" style="margin-bottom: 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8486191632104654344-7412297749783367560?l=mdxdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdxdax.blogspot.com/feeds/7412297749783367560/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mdxdax.blogspot.com/2011/11/avoid-pitfalls-of-fact-data-prefetching.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/7412297749783367560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/7412297749783367560'/><link rel='alternate' type='text/html' href='http://mdxdax.blogspot.com/2011/11/avoid-pitfalls-of-fact-data-prefetching.html' title='Avoid Pitfalls of Fact Data Prefetching'/><author><name>Jeffrey Wang</name><uri>http://www.blogger.com/profile/09745744072887789758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-tu8Xkl7uEjs/TsMNZQXaMYI/AAAAAAAAAEM/V5iPSnYNwz8/s72-c/Q1ProfilerTrace.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8486191632104654344.post-8076226745509525723</id><published>2011-10-22T17:26:00.000-07:00</published><updated>2011-10-22T17:26:19.271-07:00</updated><title type='text'>Three Strategies of Evaluating the MDX Aggregate Function</title><content type='html'>&lt;span style="font-family: Calibri;"&gt;In the past two months, the Analysis Services development team was preoccupied with wrapping up SQL Server Denali development. I was racing against time to put finishing touches on some exciting new DAX features that I will write in more details once Denali goes public. It didn’t help that PASS 2011 fell on the same week that developers were allowed to make a final batch of code changes before the checkin bar would be lifted prohibitively high. All the flurry of activity forced me to postpone writing blogs on a couple of topics queued up over the past year. Now that things have quieted down a lot on the Denali front, the development team immediately switched gear to work on the next batch of important features requested by many customers, like supporting DAX queries against multidimensional cubes. Over the next few months before Denali hits the stores, I’ll try to finish up several MDX topics that I had put on the backburner due to Denali crunch time.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Before I get to the main subject of today’s post, I’d like to say a few words on PASS Summit 2011 that happened here at Seattle about a week ago. AS team, and Microsoft at large, always encourages product developers to interact with customers through venues like PASS so that we get a chance to see firsthand how the products we have built impact people’s lives. I was gratified to see that &lt;a href="http://www.powerpivotblog.nl/"&gt;&lt;span style="color: blue;"&gt;Kasper&lt;/span&gt;&lt;/a&gt; received a round of applause when he gave the audience a glimpse of DAX query plans, a feature I personally fought very hard to be included in Denali. Obviously the room was filled with MDX users who have waited for years an MDX query plan feature. One MVP told me that she thinks MDX is a beautiful language. That was&amp;nbsp;the first time I heard the word &lt;i style="mso-bidi-font-style: normal;"&gt;beautiful&lt;/i&gt; to be associated with MDX, what I had previoulsy heard&amp;nbsp;were all in line with hard or difficult. I have also heard touching stories about how brothers both turned into MDX experts and that a mother passed her MDX knowledge to her daughter. &lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;Who could have thought that MDX can promote family bonding? I could use stories like this&amp;nbsp;to lift my spirit&amp;nbsp;after finishing another grueling product release cycle at Microsoft.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Without further delay, let’s jump into the MDX Aggregate function which is the focus of this post. Many users think of Aggregate as a smart function that dynamically chooses an aggregation type based on the current measure. But this way of thinking only works when the current measure is a physical measure that has an additive aggregation type like Sum, Min, Max, or Count. What should MDX formula engine do when the current measure is a calculated measure which doesn’t have a default aggregation type? Often times the formula engine simply gives up and returns an error, as seen in &lt;a href="http://www.bidn.com/blogs/DustinRyan/bidn-blog/1936/mdx-aggregate-functions-can-not-be-used-on-calculated-members-in-the-measures-dimension"&gt;&lt;span style="color: blue;"&gt;this blog&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;. Even when the formula engine is able to pick a calculation strategy, it often has limitations that may surprise you when you move beyond basic scenarios. In this blog post I’ll describe three execution plans the formula engine uses to evaluate the Aggregate function and the decision logic employed to pick the winning strategy. The information provided here is valid as of SQL Server 2008R2.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Here are the three possible execution plans for calculating the value &lt;i style="mso-bidi-font-style: normal;"&gt;V&lt;/i&gt; of&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Aggregate(«Set»[, «Numeric Expression»]) &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;in the context of the current cell &lt;em&gt;C&lt;/em&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&lt;sub&gt;0&amp;nbsp; &lt;/sub&gt;&lt;/em&gt;&lt;span style="font-size: small;"&gt;whose subspace is &lt;em&gt;S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;0&lt;/span&gt;&lt;/sub&gt;&lt;/em&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-family: Calibri; mso-bidi-font-size: 11.0pt; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;1.&lt;/span&gt;&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The basic plan.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Many people think of Aggregate as a generic form of Sum, Min, Max, or Count with a similar execution strategy.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Let &lt;i style="mso-bidi-font-style: normal;"&gt;Agg&lt;/i&gt; be the aggregation function derived from the current measure in &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;0&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;i style="mso-bidi-font-style: normal;"&gt;Set V&lt;/i&gt; = NULL&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;For each tuple &lt;i style="mso-bidi-font-style: normal;"&gt;t&lt;/i&gt; in «Set»&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.75in;"&gt;&lt;span style="font-family: Calibri;"&gt;Apply &lt;i style="mso-bidi-font-style: normal;"&gt;t&lt;/i&gt; to &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;0&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt; to build a new subspace &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;1&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;If «Numeric Expression» is present&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1.25in;"&gt;&lt;span style="font-family: Calibri;"&gt;Set &lt;i style="mso-bidi-font-style: normal;"&gt;V&lt;/i&gt; = &lt;i style="mso-bidi-font-style: normal;"&gt;Agg&lt;/i&gt;(&lt;i style="mso-bidi-font-style: normal;"&gt;V&lt;/i&gt;, value of «Numeric Expression» in &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;1&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;Else&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 1.25in;"&gt;&lt;span style="font-family: Calibri;"&gt;Set &lt;i style="mso-bidi-font-style: normal;"&gt;V&lt;/i&gt; = &lt;i style="mso-bidi-font-style: normal;"&gt;Agg&lt;/i&gt;(&lt;i style="mso-bidi-font-style: normal;"&gt;V&lt;/i&gt;, value property of &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;1&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The formula engine chooses this strategy when the current measure in&lt;i style="mso-bidi-font-style: normal;"&gt; S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;0&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt; is a basic physical measure or is an alias to a basic physical measure, as shown below.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-gIyD7YV_Y4s/TqNK66XbGKI/AAAAAAAAADs/vzd-ayE3i2w/s1600/basicplan_simplecalcmeasure.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="230" src="http://1.bp.blogspot.com/-gIyD7YV_Y4s/TqNK66XbGKI/AAAAAAAAADs/vzd-ayE3i2w/s640/basicplan_simplecalcmeasure.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt;"&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;v:shapetype coordsize="21600,21600" filled="f" id="_x0000_t75" o:preferrelative="t" o:spt="75" path="m@4@5l@4@11@9@11@9@5xe" stroked="f"&gt;&lt;span style="font-family: Calibri;"&gt;  &lt;v:stroke joinstyle="miter"&gt;  &lt;v:formulas&gt;   &lt;v:f eqn="if lineDrawn pixelLineWidth 0"&gt;   &lt;v:f eqn="sum @0 1 0"&gt;   &lt;v:f eqn="sum 0 0 @1"&gt;   &lt;v:f eqn="prod @2 1 2"&gt;   &lt;v:f eqn="prod @3 21600 pixelWidth"&gt;   &lt;v:f eqn="prod @3 21600 pixelHeight"&gt;   &lt;v:f eqn="sum @0 0 1"&gt;   &lt;v:f eqn="prod @6 1 2"&gt;   &lt;v:f eqn="prod @7 21600 pixelWidth"&gt;   &lt;v:f eqn="sum @8 21600 0"&gt;   &lt;v:f eqn="prod @7 21600 pixelHeight"&gt;   &lt;v:f eqn="sum @10 21600 0"&gt;  &lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:formulas&gt;  &lt;v:path gradientshapeok="t" o:connecttype="rect" o:extrusionok="f"&gt;  &lt;o:lock aspectratio="t" v:ext="edit"&gt; &lt;/o:lock&gt;&lt;/v:path&gt;&lt;/v:stroke&gt;&lt;/span&gt;&lt;/v:shapetype&gt;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt;"&gt;&lt;/div&gt;&lt;div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.25in; mso-add-space: auto; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-family: Calibri; mso-bidi-font-size: 11.0pt; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;2.&lt;/span&gt;&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The switching-solve-order plan.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The basic plan stops working when the current measure is a non-trivial calculated measure since the formula engine cannot extract the &lt;i style="mso-bidi-font-style: normal;"&gt;Agg&lt;/i&gt; function any more. One way to work around the problem is to switch the solving order of the AGGREGATE function and the calculated measure. Mosha alluded to this strategy in his comment to &lt;a href="http://thomasivarssonmalmo.wordpress.com/2007/07/13/proclarity-totals-and-mdx-aggregate/"&gt;&lt;span style="color: blue;"&gt;Thomas Ivarsson’s post&lt;/span&gt;&lt;/a&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;br /&gt;&lt;span style="font-family: Calibri;"&gt;Let «Measure Expression» be the expression of the current measure in &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;0&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Set&lt;i style="mso-bidi-font-style: normal;"&gt; V&lt;/i&gt; = Calculate the value of «Measure Expression» in &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;0&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The thinking behind this strategy is that by evaluating «Measure Expression» first, it will eventually lead to a physical measure that has a good &lt;i style="mso-bidi-font-style: normal;"&gt;Agg&lt;/i&gt; function. Afterwards, the Aggregate calculation can be evaluated using the basic plan. This strategy essentially moves an otherwise higher-priority Aggregate calculation behind lower priority calculated measures.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;For example, when I slightly change the expression for calculated measure [x] to be more than just a physical measure name, the formula engine would switch the solving orders of [x] and [y] to produce the same result as in the basic plan.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-5N1k5ErMrio/TqNK9ygSIOI/AAAAAAAAAEE/mn8dzSh7VrE/s1600/switchorderplan.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="226" src="http://2.bp.blogspot.com/-5N1k5ErMrio/TqNK9ygSIOI/AAAAAAAAAEE/mn8dzSh7VrE/s640/switchorderplan.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;span style="font-family: Calibri;"&gt;But this strategy falls apart when the calculated measure is more than just a single expression.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;If you create [x] and [y] in the cube script in the following fashion,&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;CREATE MEMBER CURRENTCUBE.Measures.[x] AS NULL;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Measures.[x] = [Measures].[Internet Sales Amount];&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;CREATE MEMBER CURRENTCUBE.[Date].[Calendar Year].[y] AS NULL; &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;[Date].[Calendar Year].[y] =&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.75in;"&gt;&lt;span style="font-family: Calibri;"&gt;AGGREGATE({[Date].[Calendar Year].&amp;amp;[2007], [Date].[Calendar Year].&amp;amp;[2008]});&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt;"&gt;&lt;br /&gt;&lt;span style="font-family: Calibri;"&gt;you will get the following surprising query result.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-NR80wxwJjhc/TqNK88mercI/AAAAAAAAAD8/JrHEr8EgByA/s1600/switchorder_dontwork.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="144" src="http://3.bp.blogspot.com/-NR80wxwJjhc/TqNK88mercI/AAAAAAAAAD8/JrHEr8EgByA/s200/switchorder_dontwork.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt;"&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;This is because the formula engine can only retrieve the original expression of the calculated measure but is unable to take into account scope assignments which also affect the value of the calculated measure. In my opinion, this strategy is more or less a hack as it doesn’t provide a coherent solution under all circumstances. &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt;"&gt;&lt;/div&gt;&lt;div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.25in; mso-add-space: auto; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-family: Calibri; mso-bidi-font-size: 11.0pt; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;3.&lt;/span&gt;&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The set-in-the-where-clause plan.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoListParagraph" style="margin: 0in 0in 10pt 0.25in; mso-add-space: auto; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Neither of the above strategies works when the current measure is a physical measure with a non-additive function, such as semi-additive measures or distinct count measures. To make the function return meaningful result, we borrowed a page from another hacky feature of MDX: multi-select through query-scope calculated member using Aggregate function. The formula engine rewrites the incoming multi-select query into an equivalent query by putting the set argument extracted from the Aggregate function into the where clause.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/--gwV51apBNQ/TqNK8ERZXnI/AAAAAAAAAD0/eWMCukhINO8/s1600/replace_calcmember_setinwhere.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="346" src="http://2.bp.blogspot.com/--gwV51apBNQ/TqNK8ERZXnI/AAAAAAAAAD0/eWMCukhINO8/s640/replace_calcmember_setinwhere.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;As it turned out, the same strategy can be used as a generic solution for evaluating the Aggregate function. In 2008R2, this is used for non-additive physical measures.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Construct a new subspace &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;1&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt; by adding «Set» as a slice to &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;0&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;If «Numeric Expression» is present&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.75in;"&gt;&lt;span style="font-family: Calibri;"&gt;Set &lt;i style="mso-bidi-font-style: normal;"&gt;V&lt;/i&gt; = Calculate the value of «Numeric Expression» in &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;1&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Else&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.75in;"&gt;&lt;span style="font-family: Calibri;"&gt;Set &lt;i style="mso-bidi-font-style: normal;"&gt;V&lt;/i&gt; = Calculate the value property of &lt;i style="mso-bidi-font-style: normal;"&gt;S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;1&lt;/span&gt;&lt;/sub&gt;&lt;/i&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 0pt 0.5in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;If you are familiar with DAX, this strategy is similar to the Calculate function in DAX: it transforms the current subspace by applying the set argument as a filter and then evaluates the «Numeric Expression» in the new subspace. &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Conclusion&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;As you can see from today’s discussion, current implementation of the Aggregate function in the face of a calculated measure has limitations and inconsistencies. It may&amp;nbsp;cause confusions among users&amp;nbsp;who&amp;nbsp;saw that basic scenarios worked and then ventured into more advanced usages. Therefore we are considering to&amp;nbsp;give users an option to switch to the set-in-the-where-clause plan where currently the switching-solve-order plan is used.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8486191632104654344-8076226745509525723?l=mdxdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdxdax.blogspot.com/feeds/8076226745509525723/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mdxdax.blogspot.com/2011/10/three-strategies-of-evaluating-mdx.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/8076226745509525723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/8076226745509525723'/><link rel='alternate' type='text/html' href='http://mdxdax.blogspot.com/2011/10/three-strategies-of-evaluating-mdx.html' title='Three Strategies of Evaluating the MDX Aggregate Function'/><author><name>Jeffrey Wang</name><uri>http://www.blogger.com/profile/09745744072887789758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-gIyD7YV_Y4s/TqNK66XbGKI/AAAAAAAAADs/vzd-ayE3i2w/s72-c/basicplan_simplecalcmeasure.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8486191632104654344.post-2254440106274289653</id><published>2011-08-17T15:49:00.000-07:00</published><updated>2011-08-17T15:49:27.476-07:00</updated><title type='text'>Interaction between MDX Subselect and Calculation</title><content type='html'>&lt;span style="font-family: Calibri;"&gt;As Mosha &lt;/span&gt;&lt;span style="color: black; mso-themecolor: text1;"&gt;&lt;span style="font-family: Calibri;"&gt;Pasumansky&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="color: black; mso-themecolor: text1;"&gt; &lt;/span&gt;has described in his blog &lt;i style="mso-bidi-font-style: normal;"&gt;&lt;a href="http://sqlblog.com/blogs/mosha/archive/2008/11/04/as2008-mdx-subselects-and-create-subcube-in-non-visual-mode.aspx"&gt;&lt;span style="color: blue;"&gt;AS2008MDX: subselects and CREATE SUBCUBE in non-visual mode&lt;/span&gt;&lt;/a&gt;&lt;/i&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;, an MDX subselect performs two functions:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Limits each axis set through dimension autoexists.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: Calibri;"&gt;Applies visualtotals to cell values if there are no coordinate overwrites.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The second point deserves more elaboration especially when there are MDX calculations involved. In this blog post, I will explain how subselect visualtotals works in MDX formula engine and how the presence of MDX calculations can disable visualtotals by overwriting subselect attributes. Let’s start by looking at a series of questions recently raised by an AS customer. Since the original questions were based on customer’s database, I have adapted them to using AdventureWorks.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-family: Calibri; mso-bidi-font-size: 11.0pt; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;1. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;A customer puzzle&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;First run the following MDX query to find out the original values of USA, CA, and WA.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;a href="http://3.bp.blogspot.com/-uc_n13rCotI/Tkw9N_r8UII/AAAAAAAAACM/fwBFAnObXfQ/s1600/Figure1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="165" src="http://3.bp.blogspot.com/-uc_n13rCotI/Tkw9N_r8UII/AAAAAAAAACM/fwBFAnObXfQ/s400/Figure1.png" width="400" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;v:shapetype coordsize="21600,21600" filled="f" id="_x0000_t75" o:preferrelative="t" o:spt="75" path="m@4@5l@4@11@9@11@9@5xe" stroked="f"&gt;&amp;nbsp;&amp;nbsp;&lt;v:stroke joinstyle="miter"&gt;&amp;nbsp;&amp;nbsp;&lt;v:formulas&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;v:f eqn="if lineDrawn pixelLineWidth 0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;v:f eqn="sum @0 1 0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;v:f eqn="sum 0 0 @1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;v:f eqn="prod @2 1 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;v:f eqn="prod @3 21600 pixelWidth"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;v:f eqn="prod @3 21600 pixelHeight"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;v:f eqn="sum @0 0 1"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;v:f eqn="prod @6 1 2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;v:f eqn="prod @7 21600 pixelWidth"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;v:f eqn="sum @8 21600 0"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;v:f eqn="prod @7 21600 pixelHeight"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;v:f eqn="sum @10 21600 0"&gt;&amp;nbsp;&amp;nbsp;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:f&gt;&lt;/v:formulas&gt;&amp;nbsp;&amp;nbsp;&lt;v:path gradientshapeok="t" o:connecttype="rect" o:extrusionok="f"&gt;&amp;nbsp;&amp;nbsp;&lt;o:lock aspectratio="t" v:ext="edit"&gt; &lt;/o:lock&gt;&lt;/v:path&gt;&lt;/v:stroke&gt;&lt;/v:shapetype&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;v:shapetype coordsize="21600,21600" filled="f" o:preferrelative="t" o:spt="75" path="m@4@5l@4@11@9@11@9@5xe" stroked="f"&gt;&lt;v:stroke joinstyle="miter"&gt;&lt;v:path gradientshapeok="t" o:connecttype="rect" o:extrusionok="f"&gt;&lt;o:lock aspectratio="t" v:ext="edit"&gt;&lt;/o:lock&gt;&lt;/v:path&gt;&lt;/v:stroke&gt;&lt;/v:shapetype&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;Since the value of CA is $5,714,257.69, if we query USA while subselecting by CA, the visual totaled value of USA is $5,714,257.69 as well.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-s4XFv9CF08o/Tkw9Oz8Ko3I/AAAAAAAAACQ/TtayIEujTeY/s1600/Figure2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="115" src="http://2.bp.blogspot.com/-s4XFv9CF08o/Tkw9Oz8Ko3I/AAAAAAAAACQ/TtayIEujTeY/s640/Figure2.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Case 1&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Now if you insert a seemingly innocuous calculation into the cube script that simply says USA = USA, &lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-IeVQ1dGhuiM/Tkw9P8bta4I/AAAAAAAAACU/jjAWLSGH1tU/s1600/Figure3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="44" src="http://2.bp.blogspot.com/-IeVQ1dGhuiM/Tkw9P8bta4I/AAAAAAAAACU/jjAWLSGH1tU/s640/Figure3.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;the value of USA suddenly goes back to its original value.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-I3OYeqyQGr8/Tkw-js0EU7I/AAAAAAAAADA/vJ1-WrrngyI/s1600/Figure4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="128" src="http://4.bp.blogspot.com/-I3OYeqyQGr8/Tkw-js0EU7I/AAAAAAAAADA/vJ1-WrrngyI/s640/Figure4.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Case 2&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;span style="font-family: Calibri;"&gt;What the user really wanted was to define a calculation that calculates USA as the sum of CA and WA.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-BCmRmHLdtZM/Tkw-tYNR3KI/AAAAAAAAADE/ktE9jY8M-kI/s1600/Figure5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="56" src="http://3.bp.blogspot.com/-BCmRmHLdtZM/Tkw-tYNR3KI/AAAAAAAAADE/ktE9jY8M-kI/s640/Figure5.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;But he was not able to get visualtotals when he subselected CA. The value of USA is the sum of the values of CA and WA instead of just the value of CA.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Zbw5A-XdPQU/Tkw--Vfu7iI/AAAAAAAAADI/rDAviVCdSlo/s1600/Figure6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="124" src="http://1.bp.blogspot.com/-Zbw5A-XdPQU/Tkw--Vfu7iI/AAAAAAAAADI/rDAviVCdSlo/s640/Figure6.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Case 3&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;span style="font-family: Calibri;"&gt;The user further experimented by assigning a constant value to WA. When he put the WA assignment before the USA assignment,&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-EiN5t1di43k/Tkw_KZz62uI/AAAAAAAAADM/Q9MRmtomXTQ/s1600/Figure7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="66" src="http://3.bp.blogspot.com/-EiN5t1di43k/Tkw_KZz62uI/AAAAAAAAADM/Q9MRmtomXTQ/s640/Figure7.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;USA value was still the sum of the values of CA and WA.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-_wWKpjJ5B9w/Tkw_VPUUQvI/AAAAAAAAADQ/pxxhd9coF1s/s1600/Figure8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="124" src="http://2.bp.blogspot.com/-_wWKpjJ5B9w/Tkw_VPUUQvI/AAAAAAAAADQ/pxxhd9coF1s/s640/Figure8.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Case 4&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;span style="font-family: Calibri;"&gt;When the user moved the WA assignment after the USA assignment,&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/-bDdncKLbBrI/Tkw_cychbuI/AAAAAAAAADU/0rrv_iXRO-E/s1600/Figure9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="68" src="http://2.bp.blogspot.com/-bDdncKLbBrI/Tkw_cychbuI/AAAAAAAAADU/0rrv_iXRO-E/s640/Figure9.png" width="640" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;he suddenly got visualtotals on USA!&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-FTSIGAm2AOg/Tkw_rrZkNyI/AAAAAAAAADY/ROc2hJMdcMk/s1600/Figure10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="122" src="http://4.bp.blogspot.com/-FTSIGAm2AOg/Tkw_rrZkNyI/AAAAAAAAADY/ROc2hJMdcMk/s640/Figure10.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The above results confused quite&amp;nbsp;a few&amp;nbsp;MDX users.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-family: Calibri; mso-bidi-font-size: 11.0pt; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;2. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;How does subselect visualtotals work anyway?&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;2.1.&lt;/span&gt;&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Subselect filters without calculation&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Calibri;"&gt;You can rest assured that there is a consistent logic underneath the above perplexing results. Before we study the interaction between subselect and calculation, let’s first go back to the basics to see how subselect visualtotals is attained when there is no calculation at all.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;I’ll start with a quick review of some fundamentals of the formula engine. Every MDX query is split into one or more single-granularity queries. A single-granularity query is represented by a cube subspace, also known as subcube. The formula engine constructs evaluation nodes from those single-granularity subspaces. For every evaluation node, the formula engine determines which calculations apply to its subspace and generates a list of calculation items, one for each applicable calculation. In the future, you will see that calculation item is also called evaluation node item. But I will stick with calculation item in this post. Every calculation is associated with a subspace at the granularities where the calculation is defined. For example, the left side of the trivial assignment USA = USA defines a subspace with granularity at Country level. The formula engine then constructs a subspace for each calculation item by combining the evaluation node subspace with the calculation subspace. The process of constructing an item subspace is too complex to be covered here, but the resulting subspace is always at or below the granularities of the evaluation node subspace. That’s because a calculation simply doesn’t apply to an evaluation node if the subspace of the former is not strictly at or below the granularities of the subspace of the latter. For example, an assignment at the Country level does not affect a query at the City level. The diagram below illustrates an evaluation node and its calculation items. &lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-7ULmMNNK3V4/Tkw_5TYr7yI/AAAAAAAAADc/iUDbjG_1y5s/s1600/CoverItemSubspaces.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="241" src="http://2.bp.blogspot.com/-7ULmMNNK3V4/Tkw_5TYr7yI/AAAAAAAAADc/iUDbjG_1y5s/s400/CoverItemSubspaces.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;In the simplest case when there is no calculation like calculated member, scope assignment, unary operator, etc., the formula engine creates a single, special calculation item, called DetailData, which fetches data from the storage engine. You can imagine that the subspace associated with any DetailData calculation item is always at the lowest granularities for the measures to be fetched. Any subselect filters are then used to filter out unwanted members from the DetailData subspace. Afterwards, when the formula engine aggregates measure values from the DetailData subspace into the evaluation node subspace, you get visualtotals since data has been filtered at the lowest level. In practice, the formula engine does not construct DetailData subspace at the lowest granularities since the storage engine can do more than just retrieving and filtering data at leaf levels, it can also aggregate physical measure values at higher granularities. So the DetailData subcubes sent to the storage engine, as shown in SQL Profiler’s Query Subcube trace events, are typically at higher granularities but include any subselect filters as subcube slices which will filter data at leaf levels.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;2.2.&lt;/span&gt;&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Subselect filters with calculations.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Calibri;"&gt;As we just said, when there is no applicable calculation, visualtotals is achieved by applying filters to the DetailData subspace and then aggregating measure values into a higher granularity subspace. The same logic extends naturally to cases when calculations come into the picture. Unlike DetailData items, the subspace of an arbitrary calculation is not necessarily at the lowest granularities any more. When building the subspace of the calculation item for a calculation, the formula engine examines each subselect attribute one by one, applies a subselect filter only if the attribute is at or above the granularities of the subspace. So if a subspace is at quarter level, subselect filters at quarter or year levels will be applied to the subspace but subselect filters at month or day levels are skipped. The diagram below illustrates how a subselect partially filters a subspace.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-4bI3mIhCz9Y/TkxAWPiorRI/AAAAAAAAADg/7kpv5Np4N_w/s1600/SubselectPartialApply.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="222" src="http://4.bp.blogspot.com/-4bI3mIhCz9Y/TkxAWPiorRI/AAAAAAAAADg/7kpv5Np4N_w/s400/SubselectPartialApply.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-family: Calibri;"&gt;In practice, every time the formula engine constructs a new subspace, be it for an evaluation node or a calculation item, it always applies the subset of subselect filters which are at or above the granularities of the new subspace.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;2.3.&lt;/span&gt;&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Attributes overwritten by calculations&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Calibri;"&gt;An MDX calculation is not only defined by the subspace to which it applies, but also by its MDX expression. When the formula engine evaluates an MDX expression, it often transforms one subspace into another by overwriting some of the attributes. For example, MDX tuple expression ([Retailer Sales Amount], [Date].[Fiscal Year].[FY 2011]) changes one subspace to another by overwriting the [Measures] attribute and the [Fiscal Year] attribute and its related attributes. More complex MDX calculation expressions are parsed into formula trees. Subexpressions within a formula tree like tuple expressions or set expressions overwrite attributes in the original subspace to produce new subspaces.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;While the formula engine navigates from one subspace to another, through evaluation nodes and calculation items, it keeps track of all attributes that have been overwritten by calculation expressions so far. When it is time to apply subselect filters to a newly constructed subspace, the formula engine skips all overwritten attributes. This rule sometimes leads to unintuitive results, like the ones we saw earlier in section 1. In case 1, the dummy calculation USA = USA overwrites attributes in the [Customer Geography] hierarchy, later on the DetailData subspace is no longer filtered by the California slice on the [State-Province] attribute, the final value for USA ends up being the sum of values of all states.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The rationale behind this rule is that if a user defines a simple calculated measure like ([Internet Sales Amount], [Fiscal Year].[FY 2009]), they really want to see the sales in 2009 when they add this measure to a report even though the report may have a filter on fiscal years 2010 and 2011. If the formula engine had applied the subselect filter after the calculated measure has changed the subspace to fiscal year 2009, user would have got empty result back since the intersection between {2009} and {2010, 2011} yields empty slice on the [Fiscal Year] attribute.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;2.4.&lt;/span&gt;&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Answers to puzzle questions&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Since calculation USA = CA + WA in case 2 and case 3 overwrites attributes in the [Customer Geography] hierarchy as well, the same rule kicks in to prevent the subselect filter on [State-Province] from being applied, hence no visualtotals for USA. The diagram below illustrates that in cases 1 through 3, overwritten attributes prevents subselect visualtotals.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-N1Ixz8uL0oE/TkxAnMz00wI/AAAAAAAAADk/-Jwq7xAV8O4/s1600/SubselectNotApply.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://2.bp.blogspot.com/-N1Ixz8uL0oE/TkxAnMz00wI/AAAAAAAAADk/-Jwq7xAV8O4/s640/SubselectNotApply.png" width="486" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;But what about case 4 when WA = 1000000 is moved after USA = CA + WA? Why did we get visualtotals in that case? This is actually nothing more than a trick question to test how well you know solving orders in MDX. Now that calculation WA = 1000000 has a higher calculation pass value than calculation USA = CA + WA, the latter calculation is not used at all. The diagram below shows that since calculation does not overwrite any attributes, subselect filters still apply.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-SlOdzGXVzTg/TkxA0sIoQYI/AAAAAAAAADo/iKRToEFFhJg/s1600/SubselectDoesApply.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="323" src="http://1.bp.blogspot.com/-SlOdzGXVzTg/TkxA0sIoQYI/AAAAAAAAADo/iKRToEFFhJg/s640/SubselectDoesApply.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;2.5.&lt;/span&gt;&lt;span style="font-size-adjust: none; font-stretch: normal; font: 7pt/normal &amp;quot;Times New Roman&amp;quot;;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Caveats&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Note that the rule discussed in 2.3 only applies to subselect visualtotals. MDX VisualTotals function is not affected by overwritten attributes in the same way. The discrepancy between the two styles of visualtotals is due to historical reasons where VisualTotals function had to maintain backward compatibility with SQL Server 2000 behavior.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Also note that the current implementation has complications when an MDX query mixes subselect with set in the where clause. So it’s generally not a good idea to use both features together in the same query.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-family: Calibri; mso-bidi-font-size: 11.0pt; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;3. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;What if a subselect is arbitrarily shaped?&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;So far we have been applying subselect filters one attribute at a time. We have learned that for a given subspace, some subselect filters can be applied if they are at or above granularity and not overwritten, others cannot be applied if they are below granularity or have been overwritten. This is not an issue when each subselect attribute can be applied independently. What if there is a correlation between two subselect attributes? In AS jargon, what if a subselect is arbitrarily shaped but only a subset of the attributes can be applied to a subspace? In this case, the formula engine projects the subselect onto the applicable filter attributes and then restricts the subspace with the projected set. But if a partial projection is caused by some of the filter attributes overwritten by calculations, the formula engine raises an error instead. For example, insert a dummy calculation WA = WA into the cube script that overwrites the [State-Province] attribute. Issue a query &lt;i style="mso-bidi-font-style: normal;"&gt;Select USA From (Select {(CA, 2009), (WA, 2008)} From AW)&lt;/i&gt; which contains an arbitrary shape subselect and you will get the error &lt;i style="mso-bidi-font-style: normal;"&gt;Expression cannot be resolved in the context of an arbitrary shape&lt;/i&gt;. That’s because the [Fiscal Year] attribute of the arbitrary shape set applies to the subspace but the [State-Province] attribute of the arbitrary shape set does not apply as it has been overwritten by the dummy calculation.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-family: Calibri; mso-bidi-font-size: 11.0pt; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;4. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Summary&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Today we have learned how MDX formula engine implements subselect visualtotals. In general, subselect filters newly constructed subspaces for attributes at or above granularities. The DetailData calculation item can be thought of as working at the leaf levels therefore all subselect filters apply. Other calculation items may work at higher levels hence only a subset of subselect filters are used to restrict&amp;nbsp;their subspaces. Attributes overwritten by calculations are not filtered by subselect.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8486191632104654344-2254440106274289653?l=mdxdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdxdax.blogspot.com/feeds/2254440106274289653/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mdxdax.blogspot.com/2011/08/interaction-between-mdx-subselect-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/2254440106274289653'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/2254440106274289653'/><link rel='alternate' type='text/html' href='http://mdxdax.blogspot.com/2011/08/interaction-between-mdx-subselect-and.html' title='Interaction between MDX Subselect and Calculation'/><author><name>Jeffrey Wang</name><uri>http://www.blogger.com/profile/09745744072887789758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-uc_n13rCotI/Tkw9N_r8UII/AAAAAAAAACM/fwBFAnObXfQ/s72-c/Figure1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8486191632104654344.post-4855499335707106094</id><published>2011-06-27T18:32:00.000-07:00</published><updated>2011-06-28T23:20:38.099-07:00</updated><title type='text'>Under the Covers: MDX IF Statement</title><content type='html'>&lt;span style="font-family: Calibri;"&gt;It is a well-known best practice in the MDX community to avoid run-time checks by choosing SCOPE over IIF function, and for the same reason, the IF statement. But what is the actual performance impact when you have no choice&amp;nbsp;but to use&amp;nbsp;IIF function or IF statement? I have described in details the block mode algorithm for IIF function in one of my &lt;a href="http://mdxdax.blogspot.com/2011/01/mdx-iif-execution-plans-and-plan-hints.html"&gt;&lt;span style="color: blue;"&gt;previous blog posts&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;. The other day, &lt;a href="http://prologika.com/CS/blogs/blog/default.aspx"&gt;&lt;span style="color: blue;"&gt;Teo Lachev&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt; asked whether he needed to worry about performance if he used IF statement in his cube script. In particular, Teo wanted to know if there was any performance impact on other calculations which kick in when the condition of&amp;nbsp;IF statement is false. In my post about IIF function, I mentioned that IF statement is internally rewritten as IIF function calls. Today I am going to add a bit more details on how the rewriting is done and what limitations can prevent the rewriting from happening. What is described here applies equally to the CONDITION clause in a CREATE CELL CALCULATION statement since there is no internal difference between the two MDX features.&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&amp;nbsp; &lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Rewrite to IIF function calls&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Let’s consider a simple case where two calculations apply to the same subspace S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;0&lt;/span&gt;&lt;/sub&gt;, as shown in Figure 1. The calculation, Calc1, wrapped in IF statement has higher priority over the other calculation, Calc2. For example, Calc1 may be at a higher calculation&amp;nbsp;pass&amp;nbsp;than Calc2. When comparing two scope specifications, MDX calculation engine does not take into account conditions of IF statements although they appear to be part of the scope definitions. Instead,&amp;nbsp;conditions in IF statements are evaluated at run-time. &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-BJdX5qI8PS4/Tgkf_RCpbBI/AAAAAAAAACE/1X74OY3qGis/s1600/Figure1.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="391" src="http://1.bp.blogspot.com/-BJdX5qI8PS4/Tgkf_RCpbBI/AAAAAAAAACE/1X74OY3qGis/s400/Figure1.gif" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;In case you wonder why Calc1 and Calc2 have their own subspaces S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;1&lt;/span&gt;&lt;/sub&gt; and S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;2&lt;/span&gt;&lt;/sub&gt; even though the evaluation node already has a subspace S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;0&lt;/span&gt;&lt;/sub&gt;, that’s because the scope of a calculation can be at lower granularity than the subspace of an evaluation node. For example, a query may ask for results at the year level, but there is a calculation at month level. In this case, the calculation is needed to answer the query but the subspace for the evaluation node, which is the same as the subspace of the query, and the subspace of the calculation will be at different granularities.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Figure 2 shows how the IF statement is translated to IIF function calls which are evaluated at run-time. DisjointTest is an internal function that takes as input a given cell and returns true if the cell is not covered by one of the higher priority calculations. In our example, when S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;1&lt;/span&gt;&lt;/sub&gt; and S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;2&lt;/span&gt;&lt;/sub&gt; are at the same granularity, DisjointTest degenerates into NOT Condition, which returns true when the condition of IF statement returns false. When S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;2&lt;/span&gt;&lt;/sub&gt; has lower granularity than S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;1&lt;/span&gt;&lt;/sub&gt;, DisjointTest first finds a cell in S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;1&lt;/span&gt;&lt;/sub&gt; that covers the given cell in S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;2&lt;/span&gt;&lt;/sub&gt; and then evaluates NOT Condition in the context of the covering cell.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-jEUmmrp_vWY/TgkaPMiYXNI/AAAAAAAAACA/Fw4VgdPfpqY/s1600/Figure2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="338" src="http://2.bp.blogspot.com/-jEUmmrp_vWY/TgkaPMiYXNI/AAAAAAAAACA/Fw4VgdPfpqY/s400/Figure2.gif" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;So unlike IIF(Condition, Calc1, Calc2), where the Condition is evaluated in one subspace, the condition of IF statement is replicated and evaluated in all subspaces of lower priority calculations which apply to the given evaluation node. Consequently, the condition of IF statement will be evaluated in many more cells than the original subspace, especially when the subspaces of lower priority calculations are at lower granularities.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Exceptions&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The internal rewriting to IIF does not happen in S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;2&lt;/span&gt;&lt;/sub&gt; when Calc2 is a semi-additive measure, a unary operator, or a storage engine query. In those cases, Calc2 is evaluated in a larger subspace not constrained by the opposite condition of the IF statement. This is typically not a problem when Calc2 is to simply fetch data from the storage engine except for really large cubes when fetching the extra data requires a lot of disk IOs. In the other two cases, S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;2&lt;/span&gt;&lt;/sub&gt; becomes inexact since now Calc2 is evaluated in more cells than it should. An inexact subspace increases the chance of the MDX calculation engine choosing cell-by-cell mode when it builds the calculation subtree starting from S&lt;sub&gt;&lt;span style="font-size: x-small;"&gt;2&lt;/span&gt;&lt;/sub&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8486191632104654344-4855499335707106094?l=mdxdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdxdax.blogspot.com/feeds/4855499335707106094/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mdxdax.blogspot.com/2011/06/under-covers-mdx-if-statement.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/4855499335707106094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/4855499335707106094'/><link rel='alternate' type='text/html' href='http://mdxdax.blogspot.com/2011/06/under-covers-mdx-if-statement.html' title='Under the Covers: MDX IF Statement'/><author><name>Jeffrey Wang</name><uri>http://www.blogger.com/profile/09745744072887789758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-BJdX5qI8PS4/Tgkf_RCpbBI/AAAAAAAAACE/1X74OY3qGis/s72-c/Figure1.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8486191632104654344.post-3123913530001315943</id><published>2011-05-31T23:07:00.000-07:00</published><updated>2011-05-31T23:07:38.641-07:00</updated><title type='text'>Performance Considerations for Recursive Calculations in MDX (Part 2)</title><content type='html'>&lt;span style="font-family: Calibri;"&gt;&lt;a href="http://mdxdax.blogspot.com/2011/04/performance-considerations-for.html"&gt;&lt;span style="color: blue;"&gt;Last time&lt;/span&gt;&lt;/a&gt; I discussed MDX engine limitations in dealing with recursive calculations. Today I want to describe two more situations where users may run into bad performance when writing recursive calculations in MDX.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="font-size: large;"&gt;Pseudo Infinite Recursion&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Last time I recommended users to avoid subspace overlap over the changing attribute of the recursion, in most cases, an attribute in the Date/Time dimension. That’s because MDX calculation engine may choose a cell-by-cell execution plan when it detects sideways recursion. But performance can get a lot worse than simply executing in cell-by-cell mode if MDX calculation engine falsely reports an infinite recursion even though it is actually a sideways recursion. When a calculation applies to two subspaces on the callstack, MDX calculation engine checks for potential infinite recursion. When the two subspaces have overlapping regions, MDX calculation engine checks to see if any cell in one subspace is mapped to itself in the other subspace. This requires MDX calculation engine to keep track of how each MDX expression on the callstack transforms one subspace into another. While there are extensive logic inside MDX formula engine to analyze most common MDX expressions, there are still some MDX expressions which are treated as a black box by the formula engine. Moreover, if one of the subspaces on the callstack is a single-cell subspace, MDX calculation engine switches to lazy execution mode for that expression, and treats the calculation in that subspace as opaque as well. During infinite recursion detection, an opaque calculation on the callstack would force MDX calculation engine to assume the worst and to raise an infinite recursion error even though it is not true.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-IOsGPIja0Oc/TeXEhxVhiUI/AAAAAAAAAB4/qy13oZxl0CU/s1600/PseudoRecursion.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="477" src="http://4.bp.blogspot.com/-IOsGPIja0Oc/TeXEhxVhiUI/AAAAAAAAAB4/qy13oZxl0CU/s640/PseudoRecursion.gif" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Error handling is one of the most expensive operations in MDX calculation unless the error simply aborts the entire query. This is especially true in block mode. MDX calculation engine is not sure whether the error happens in one of the cells in the subspace or the error applies to the entire subspace. As a result, parent evaluation node which intercepts the error will abandon all intermediate results and start all over by falling back to cell-by-cell mode and recalculating cell values one by one. For the same reason, if an infinite recursion error is raised due to overlapping region and opaque MDX expression anywhere on the callstack, error handling logic at upper level would force a recomputation of cell values one at a time. This is helpful since if the infinite recursion is not real, it won’t happen again as soon as the changing attribute is reduced to a single member. However, the unwinding process happens one level at a time. If the recursion loop is long, recomputations of cell values at all intermediate levels are wasted effort, see Figure 2. &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-JKW_0yBYJ5M/TeXDrDIfpbI/AAAAAAAAABk/UNndZu6Y1OA/s1600/ErrorHandling.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="528" src="http://3.bp.blogspot.com/-JKW_0yBYJ5M/TeXDrDIfpbI/AAAAAAAAABk/UNndZu6Y1OA/s640/ErrorHandling.gif" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The false infinite recursion error is repeatedly raised until the beginning of the recursion loop is reached. Only when MDX calculation engine splits the subspace at the beginning of the recursion into individual cells will the false infinite recursion error stops being raised, as by now the beginning subspace would have a single member on the changing attribute and the ending subspace would have a different member on that attribute. To make matters worse, MDX calculation engine has a preference for block mode. Even though a parent level is forced into cell-by-cell mode to avoid false infinite recursion, a child level may still make the same mistake if somehow the subspace is enlarged by some calculation to include more members on the changing attribute. If you see a steady increase of performance counter &lt;em&gt;MDX\Total Recomputes&lt;/em&gt; along with the creation of large numbers of evaluation nodes of various kinds, your query may have entered such a vicious cycle.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-PoqD6bSbkmE/TeXDxNGjk6I/AAAAAAAAAB0/AmwVr9mpGag/s1600/Recomputes.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="15" src="http://3.bp.blogspot.com/-PoqD6bSbkmE/TeXDxNGjk6I/AAAAAAAAAB0/AmwVr9mpGag/s400/Recomputes.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="font-size: large;"&gt;Impact on Calculation Caches&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Aggressively caching intermediate results is one of the key reasons for MDX execution engine to deliver great query performance. MDX execution engine maintains a complex system of various types of caches for different purposes. When a MDX query requires heavy calculation, caches for evaluation nodes tend to play a decisive role in good query performance. An evaluation node is a subspace along with query plans built for all applicable calculations plus, optionally, data caches holding the calculation results. Unlike cached results of storage engine queries which correspond to leaf nodes in an MDX evaluation tree, formula engine evaluation nodes can be at much higher level or even be the root node of an evaluation tree. Hitting or missing an evaluation node at high level in the cache will make a dramatic difference in performance for calculation intensive queries.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;MDX calculation engine keeps separate caches for cell-by-cell evaluation nodes and for bulk-mode evaluation nodes. In this section I am going to discuss the impact of recursive calculation on bulk-mode evaluation node caches.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The evaluation node cache mentioned above builds hash tables and indexes to facilitate insertions and lookups of cache entries. The hash function used by the hash table calculates hash values based on the group-by attributes of a subspace, plus some other information which is unimportant for the sake of this discussion. The hash table uses linked lists to implement separate chaining for collision resolution. Since every evaluation node ever created is inserted into the cache, the cache becomes crowded very fast. When&amp;nbsp;a linked list becomes too long, evaluation nodes are evicted from the cache, as reflected by the performance counter &lt;em&gt;MDX\Number of evictions of evaluation nodes&lt;/em&gt;.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Recursion can easily generate a large number of evaluation nodes. Starting from the original query subspace, the evaluation tree can grow quite big as recursion grows deeper and deeper. This in turn puts heavy pressure on evaluation node caches. To exacerbate the situation, the hash function mentioned previously skips group by attributes in parent child dimensions, as a result, subspaces with a lot of parent child dimensions have a much higher chance of hash collision. On the other hand, recursive calculations tend to show up in financial cubes which usually contain a lot of parent child dimensions. So recursion in a cube with a lot of parent child dimensions has a high chance of eviction of cached evaluation nodes and a low chance of hitting a previously built evaluation node.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-AaxLC5PY4Sc/TeXDtzp1n4I/AAAAAAAAABs/wmfe6k1GdMc/s1600/LargeEvaluationTree.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://2.bp.blogspot.com/-AaxLC5PY4Sc/TeXDtzp1n4I/AAAAAAAAABs/wmfe6k1GdMc/s640/LargeEvaluationTree.gif" width="392" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-B54h4nDm53Q/TeXDsQePR-I/AAAAAAAAABo/a-ygTi3WI8M/s1600/HashCollision.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="140" src="http://3.bp.blogspot.com/-B54h4nDm53Q/TeXDsQePR-I/AAAAAAAAABo/a-ygTi3WI8M/s640/HashCollision.gif" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;You can increase the maximum length of all linked lists by increasing the values of private server configuration properties &lt;em&gt;CalculationLRUMinSize&lt;/em&gt; and &lt;em&gt;CalculationLRUMaxSize&lt;/em&gt; as the eviction threshold is dynamically calculated but always falls in the interval [&lt;em&gt;CalculationLRUMinSize&lt;/em&gt;, &lt;em&gt;CalculationLRUMaxSize&lt;/em&gt;]. Increasing the size of the linked lists only allows more evaluation nodes to stay in the cache. You also have to increase the value of private server configuration property &lt;em&gt;CalculationCacheRegistryMaxIterations&lt;/em&gt; so that those entries are actually examined during cache lookup.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="font-size: large;"&gt;Summary&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;In this blog post, we explored two more scenarios in which the presence of recursive MDX calculations can&amp;nbsp;negatively impact query performance. MDX calculation engine may raise false infinite recursion errors&amp;nbsp;when the changing attribute has more than one member in the subspace and when there are a mix of block mode evaluation nodes and cell-by-cell mode evaluation nodes along the recursion path. Although not a definitive diagnosis, you can watch the performance counter &lt;em&gt;Total recomputes&lt;/em&gt; to get an indication that unwarranted errors are causing the query slowdown. As recommended in my previous post, keeping a single member on the changing&amp;nbsp;attribute&amp;nbsp;will prevent this issue.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;We often find recursive calculations in financial cubes, which also tend to have many parent child dimensions. The combination of the two is cache unfriendly for bulk mode evaluation nodes. Here is one way to help you identify this problem. Assume there is a recursive calculation based on the [Month] attribute. First issue a query to calculate the value in January. After the query finishes, issue a query to calculate the value in February. After that, issue a query to calculate the value in March, so on so forth. If each query comes back fast in this fashion of successive calculations but a query to calculate the value in December is slow when starting in cold cache mode, this is an indication that your recursive calculation can benefit from hitting previously cached results but the large number of evaluation nodes generated by a deep recursion is evicting good cached results. Sometimes increasing the maximum size of hash collision chain of the evaluation node cache may help.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Most of these problems arise because block mode evaluation can be improved in terms of infinite recursion detection and sideways recursion handling. While that may happen in a future release of Analysis Services, a potential workaround&amp;nbsp;is to force a pure cell-by-cell mode for all calculations. SQL Server 2000 performed calculations in cell-by-cell mode only. Many cubes designed back in SQL Server 2000 days worked well enough in that mode with acceptable and predictable query performance. If none of&amp;nbsp;my other recommendations work for you and you suspect that&amp;nbsp;pure cell-by-cell mode&amp;nbsp;may be what you need, you can contact Microsoft Customer Support and Services to explore such a possibility.&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;img height="3" src="http://3.bp.blogspot.com/-PoqD6bSbkmE/TeXDxNGjk6I/AAAAAAAAAB0/AmwVr9mpGag/s320/Recomputes.jpg" style="filter: alpha(opacity=30); left: 547px; opacity: 0.3; position: absolute; top: 1866px;" width="96" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8486191632104654344-3123913530001315943?l=mdxdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdxdax.blogspot.com/feeds/3123913530001315943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mdxdax.blogspot.com/2011/05/performance-considerations-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/3123913530001315943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/3123913530001315943'/><link rel='alternate' type='text/html' href='http://mdxdax.blogspot.com/2011/05/performance-considerations-for.html' title='Performance Considerations for Recursive Calculations in MDX (Part 2)'/><author><name>Jeffrey Wang</name><uri>http://www.blogger.com/profile/09745744072887789758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-IOsGPIja0Oc/TeXEhxVhiUI/AAAAAAAAAB4/qy13oZxl0CU/s72-c/PseudoRecursion.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8486191632104654344.post-2326948946585833120</id><published>2011-04-27T17:16:00.000-07:00</published><updated>2011-04-28T00:01:02.467-07:00</updated><title type='text'>Performance Considerations for Recursive Calculations in MDX</title><content type='html'>The other day, while investigating a customer performance problem, &lt;span style="color: blue;"&gt;Chris Webb&lt;/span&gt; came up with a sequence of very simple and targeted MDX queries against SQL Server 2008 Adventure Works database that clearly illustrate some of the pitfalls people may encounter when they write recursive MDX formulas. Today we explore how MDX formula engine generates execution plans for those queries and discuss some engine limitations in this area that may have big impact on query performance.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Chris Webb’s Queries&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Chris defined a test measure, [rtest], that recursively counts the number of days from the current date back to 07/01/2001. His first query calculates [rtest] against all customers with a slice on date 07/31/2001. The query finished in about one second to return 118,484 cells.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Query #1&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;WITH MEMBER MEASURES.rtest AS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; IIF (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Date].[Date].CURRENTMEMBER IS [Date].[Date].&amp;amp;[20010701]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , 1 + (MEASURES.rtest, [Date].[Date].CURRENTMEMBER.PREVMEMBER)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;SELECT&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;MEASURES.rtest ON 0,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;[Customer].[Customer].[Customer].MEMBERS ON 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;FROM [Adventure Works]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;WHERE ([Date].[Calendar].[Date].&amp;amp;[20010731])&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Next Chris trimmed down the number of customers to be slightly less than 50% of all customers and ran the query again. The query finished a little bit faster than the first one as expected.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Query #2&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;WITH MEMBER MEASURES.rtest AS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;IIF (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Date].[Date].CURRENTMEMBER IS [Date].[Date].&amp;amp;[20010701]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;, 1 + (MEASURES.rtest, [Date].[Date].CURRENTMEMBER.PREVMEMBER)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;SELECT&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;MEASURES.rtest ON 0,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;HEAD ([Customer].[Customer].[Customer].MEMBERS, 9241) ON 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;FROM [Adventure Works]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;WHERE ([Date].[Calendar].[Date].&amp;amp;[20010731])&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But adding one more customer to the second query suddenly increased query execution time to 20 seconds. The obvious question is what is so significant about querying 50% or more of total customers.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Query #3&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;WITH MEMBER MEASURES.rtest AS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; IIF (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Date].[Date].CURRENTMEMBER IS [Date].[Date].&amp;amp;[20010701]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , 1 + (MEASURES.rtest, [Date].[Date].CURRENTMEMBER.PREVMEMBER)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;SELECT&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; MEASURES.rtest ON 0,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; HEAD ([Customer].[Customer].[Customer].MEMBERS, 9242) ON 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;FROM [Adventure Works]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;WHERE ([Date].[Calendar].[Date].&amp;amp;[20010731])&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Chris then tried to remedy the situation by cleverly adding a helper measure, [rtest2], that pre-calculates [rtest] in the range of desired dates in the hope that calculating values of later dates can hit caches of values of earlier dates. I omitted several intermediate queries that led Chris to this idea. When he tried out his idea against the problem query, execution time was cut down to about 12 seconds, an improvement from 20 seconds.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Query #4&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;WITH MEMBER MEASURES.rtest AS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; IIF (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Date].[Date].CURRENTMEMBER IS [Date].[Date].&amp;amp;[20010701]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , 1 + (MEASURES.rtest, [Date].[Date].CURRENTMEMBER.PREVMEMBER)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;MEMBER MEASURES.rtest2 AS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; IIF (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ISEMPTY(&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SUM(&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Date].[Date].&amp;amp;[20010701] : [Date].[Date].CURRENTMEMBER,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MEASURES.rtest&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , null&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , MEASURES.rtest&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;SELECT&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; MEASURES.rtest2 ON 0,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; HEAD ([Customer].[Customer].[Customer].MEMBERS, 9242) ON 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;FROM [Adventure Works]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;WHERE ([Date].[Calendar].[Date].&amp;amp;[20010731])&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But the same trick didn’t help the original query, which now takes about 38 seconds to finish.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Query #5&lt;/em&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;WITH MEMBER MEASURES.rtest AS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; IIF (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Date].[Date].CURRENTMEMBER IS [Date].[Date].&amp;amp;[20010701]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , 1 + (MEASURES.rtest, [Date].[Date].CURRENTMEMBER.PREVMEMBER)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;MEMBER MEASURES.rtest2 AS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; IIF (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ISEMPTY(&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SUM(&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Date].[Date].&amp;amp;[20010701] : [Date].[Date].CURRENTMEMBER,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MEASURES.rtest&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , null&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; , MEASURES.rtest&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;SELECT&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; MEASURES.rtest2 ON 0,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; [Customer].[Customer].[Customer].MEMBERS ON 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;FROM [Adventure Works]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;WHERE ([Date].[Calendar].[Date].&amp;amp;[20010731])&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Block Mode vs. Cell-by-Cell Mode&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;As it turned out, queries #1 and #2 run fast because they execute in block mode. On the other hand, queries #3, #4, and #5 all execute in cell-by-cell mode. But how do I know that? Well, I admit that Analysis Services product team owes the MDX community good diagnostic features, such as MDX query plans, to easily identify such problems. Before such features become available, we have to make do with what we have today, namely PerfMon counters and SQL Profiler trace events. In this case, PerfMon counters can be very revealing. If you start PerfMon and add the counter &lt;u&gt;MSAS 2008:MDX/Total flat cache inserts&lt;/u&gt;, rerun queries #2 and #3 with cache cleared, you will see that the counter stays at 0 during query #2 but jumps to 286,502 at the end of query #3. Flat cache is one of the many data caches maintained by MDX formula engine and is used to store single-cell calculation results. The large number of inserts into this cache during query #3 indicates that the query runs in cell-by-cell mode. I'd like to add that cell-by-cell mode can be reflected in other PerfMon counters under a different circumstance. Just because &lt;u&gt;Total flat cache inserts&lt;/u&gt; is zero, does not necessarily mean query is in block mode.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Sideways Recursion and Inexact Subspace&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Now we know adding one more customer to query #2 tips MDX formula engine over the edge into cell-by-cell mode, but what is so special about the threshold of 50% of members in an attribute set? When MDX formula engine constructs a query subspace, it does not always construct the exact subspace as specified by the MDXMDX formula engine has an easy way to indicate that all customers are included in the subspace. Later operations like determining overlapping regions between two subspaces or detecting whether a cell belongs to a subspace become fast and efficient. But the real benefit of this expansion is to fetch more fact data into detail data cache, so that following queries have a much higher chance of hitting a cache entry. An obvious downside of this expansion is the possibility of fetching too much data. If there are four years of data in the cube and a query selects two years, AS engine ends up retrieving all four years of data. A much more serious problem with this expansion is when there are calculations applicable to the subspace.&amp;nbsp;A single extra member may introduce an unwanted calculation that kills performance. The 50% threshold is arbitrary and is controlled by private server configuration flag &lt;em&gt;QueryOptimizerRatio&lt;/em&gt;. Now change the ratio from -1 to 0.7 and rerun query #3, the query finishes instantly. You should know that Microsoft does not support customers who temper with private server configuration settings without authorization from Microsoft Customer Service and Support.&lt;br /&gt;&lt;br /&gt;So MDX formula engine expanded the subspace for query #3 to include all customers, the expanded subspace ended up being the same as the one in query #1, but why was query #3 so much slower than query #1? In addition to expanding the subspace in query #3, MDX formula engine also marks the query subspace as inexact for the obvious reason that the subspace contains more customers than requested. Inexact subspaces have several repercussions on building query plans. Loosely speaking, whenever MDX formula engine runs into a potentially expensive operation and when one of the parent subspaces is inexact, it is likely to fall back to cell-by-cell plan as the expensive operation may be unnecessarily introduced by the extra members added.&lt;br /&gt;&lt;br /&gt;The next concept to explain is sideways recursion. A recursion happens when the same calculation shows up twice on the stack of current calculations. When the two subspaces to which the calculation is applied have the same granularity and there is no slice change from a regular member to a calculated member or vice visa, the recursion is called sideways recursion. So if one subspace is at All level on an attribute, but the other subspace is at leaf level, the recursion is not a sideways recursion. &lt;br /&gt;&lt;br /&gt;When MDX formula engine detects a sideways recursion in the context of an inexact subspace, it chooses a cell-by-cell execution plan. There are a couple of reasons for making such a choice. &amp;nbsp;In addition to query execution, MDX formula engine is also responsible for detecting infinite recursions. Detecting infinite recursion in block mode is more complicated than in cell-by-cell mode. Even when&amp;nbsp;a calculation shows up twice on the stack of current calculations and the two subspaces to which the calculation is applied have overlapping regions, it does not necessarily entail an infinite recursion.&amp;nbsp;There&amp;nbsp;have been cases where it takes a long time to detect an infinite recursion in block mode and it turns out that time is wasted as the subspace is enlarged through expansion. So currently MDX formula engine resorts to cell-by-cell mode when&amp;nbsp;it encounters sideways recursion and when one of the parent subspaces is inexact.&amp;nbsp;If you want to keep all subspaces exact throughout the execution process to overcome this constraint, you can change another private server configuration property, &lt;em&gt;SpaceDecomposition&lt;/em&gt;, from default value of 8 to 9. You can try the new value and rerun query #3 again to see instant result. Why isn’t this default setting? Wouldn’t precise subspaces be a good thing all the time? The Analysis Services&amp;nbsp;product team tried to&amp;nbsp;make the switch&amp;nbsp;during SQL 2008 development but found that precise subspaces hurt performance much more often than helping. Precise subspaces tend to carry a lot of large slices and often arbitrary-shaped slices. Arbitrary-shaped slices are a well-known reason of MDX query performance degradation. More importantly, precise subspaces make it hard to hit caches. Extensive caching of intermediate results is one of the secret recipes of good MDX query and calculation performance.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Recursion and Subspaces Overlapping on Shifted Attributes&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Although sound promising in concept, queries #4 and #5 do not perform as well as queries #1 and #2 since they also run in cell-by-cell mode. But the subspace for query #5 is precise, why does it still enter cell-by-cell mode? The execution plan for query #5 enters cell-by-cell mode for a different reason.&lt;br /&gt;&lt;br /&gt;Chris introduced the following helper expression&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; SUM(&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Date].[Date].&amp;amp;[20010701] : [Date].[Date].CURRENTMEMBER&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ,MEASURES.rtest&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp; )&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;in the hope that MDX calculation engine will calculate [rtest] on 07/01/2001 first, and then each following day will hit the cached result of the previous day. But MDX formula engine always tries to execute in block mode first. So when constructing the subspace for the evaluation of the scalar argument of SUM, the engine adds all dates from the set argument to the subspace. The diagram below shows the important subspaces constructed when executing query #5.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-Di1-XjkHVCk/Tbh-m1UsFuI/AAAAAAAAABg/LZ7qT5hkDvo/s1600/Query5.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="300" src="http://3.bp.blogspot.com/-Di1-XjkHVCk/Tbh-m1UsFuI/AAAAAAAAABg/LZ7qT5hkDvo/s640/Query5.jpg" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;The steps below illustrate the import stages during query #5 evaluation.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Times, &amp;quot;Times New Roman&amp;quot;, serif;"&gt;Construct subspace 1 from MDX query.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Times, &amp;quot;Times New Roman&amp;quot;, serif;"&gt;Build query plan for calculation rtest2 in subspace 1.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Times, &amp;quot;Times New Roman&amp;quot;, serif;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Build query plan for sub-expression Sum(07/01/2001 : 07/31/2001, rtest)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Times, &amp;quot;Times New Roman&amp;quot;, serif;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Construct subspace 2 by adding MDX set 07/01/2001 : 07/31/2001 to subspace 1.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Times, &amp;quot;Times New Roman&amp;quot;, serif;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Build query plan for calculation rtest in subspace 2.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Times, &amp;quot;Times New Roman&amp;quot;, serif;"&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; Build query plan for sub-expression (rtest, Date.PrevMember).&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Times, &amp;quot;Times New Roman&amp;quot;, serif;"&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;Construct subspace 3 by shifting all dates in subspace 2 to the previous date.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Times, &amp;quot;Times New Roman&amp;quot;, serif;"&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; Build query plan for calculation rtest in subspace 3.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Times, &amp;quot;Times New Roman&amp;quot;, serif;"&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; Detect recursion and overlapping dates. Choose cell-by-cell plan.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When MDX formula engine detects recursion and the two subspaces have overlapping regions, it is potentially an infinite recursion. But the overlapping dates have been shifted, so whether or not there is infinite recursion depends on the MDX operation that performed the shifting. It is obvious in this case there is no infinite recursion. But MDX formula engine has to handle the general case when there are a series of shifting operations between the two subspaces. To play it safe, the engine chooses cell-by-cell execution plan again.&lt;br /&gt;&lt;br /&gt;Why is choosing cell-by-cell mode bad for performance in this case? Doesn’t the recursive formula force the engine to evaluate [rtest] one day at a time anyway? That’s true. But there are also 118,484 customers in the subspace. Right now cell-by-cell is a global decision. While going cell-by-cell over days is not a bad thing in this case, going over customers one by one is. Ideally, we want the formula engine to go block on [Customer] attribute, but cell-by-cell on [Date] attribute.&lt;br /&gt;&lt;br /&gt;Another downside of choosing cell-by-cell mode in subspace 3 is that the decision will propagate back to all parent calculations as well. MDX formula engine cannot take advantage of sparsity of underlying data when calculation is in cell-by-cell mode. Since building execution plan for [rtest] in subspace 3 is a part of building the overall execution plan for [rtest2] in subspace 1, choosing cell-by-cell plan in subspace 3 ends up forcing a bad plan for [rtest2] in subspace 1 as well.&lt;br /&gt;&lt;br /&gt;We don’t have this problem in queries #1 and #2 since there is only a single date in the subspace. When constructing a new subspace, [Date].PrevMember shifts the current date to the previous date. The newly constructed subspace has a different date from all previously constructed subspaces, therefore, there is no risk of infinite recursion. As a result, the execution plan stays in block mode.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Deep Recursion and CLR Assembly&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The next topic is unrelated to Chris Webb’s queries but still important for recursions in MDX. Each additional recursive step consumes more space on the stack. A very deep recursion will eventually use up all space on the stack. When that happens, MDX formula engine creates a fiber and switches execution on to the new fiber. But it is not always safe to call managed code from within a fiber since you may get stack overrun problem. In SQL Server 2008 R2, MDX formula engine raises an error when this happens. But the error does not abort the current query to return to user immediately. Most errors cause MDX formula engine to switch to cell-by-cell mode in case some cells contain errors but others don’t. So instead of seeing a query fail quickly, you may end up waiting a long time for it to fail eventually. Note that VBA library is registered as a CLR assembly hosted by Analysis Services, so calling VBA functions in MDX recursion may trigger the fiber exception and cause performance problems. Also note that some &lt;a href="http://cwebbbi.wordpress.com/2007/03/03/vba-functions-in-mdx/"&gt;&lt;span style="color: blue;"&gt;VBA functions&lt;/span&gt;&lt;/a&gt; have been implemented directly in Analysis Services, therefore are safe to use inside recursion. Setting private server configuration flag &lt;em&gt;AllowCLRStoredProcedureCallsInFiberMode&lt;/em&gt; to 1 would prevent the exception from being raised.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Conclusions&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;So far, we have discussed three important performance limitations imposed by MDX formula engine when it encounters recursions. We have learned that to achieve better performance when writing recursive MDX formulas, you should:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Don’t write recursive formulas unless really needed. Non-recursive MDX formulas are not subject to the limitations discussed in this post.&lt;/li&gt;&lt;li&gt;Keep the subspaces precise. Try to stay with queries that produce nice, rectangular-shaped query spaces which don’t trigger the 50% rule. Playing with &lt;em&gt;SpaceDecomposition&lt;/em&gt; is an option but you need approval from Microsoft Customer Service and Support to use it in production environment. Note that always enforcing precise subspaces is likely to have an overall&amp;nbsp;negative impact on query performance. &lt;/li&gt;&lt;li&gt;Avoid subspace overlap over shifted attributes. Most recursions happen along the time line. Keeping a single date in the subspace is one way to guarantee that subspaces don’t overlap.&lt;/li&gt;&lt;li&gt;Avoid calling into CLR assembly when recursion is very deep.&lt;/li&gt;&lt;/ol&gt;As always, performance advices apply to particular versions of a product. The recommendations given in this post apply to all currently supported&amp;nbsp;versions of Analysis Services with the latest one being 2008 R2. The Analysis Services product team will continue to evolve the product and some of the limitations are likely to be lifted in future releases. When you test your recursive calculation, you should&amp;nbsp;start at the beginning and gradually increase recursion &lt;span style="background-color: white;"&gt;depth. Observe whether query time increases at worst linearly as recursion depth increases. Make sure you test the case when the recursion is the deepest as needed by the user.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8486191632104654344-2326948946585833120?l=mdxdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdxdax.blogspot.com/feeds/2326948946585833120/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mdxdax.blogspot.com/2011/04/performance-considerations-for.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/2326948946585833120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/2326948946585833120'/><link rel='alternate' type='text/html' href='http://mdxdax.blogspot.com/2011/04/performance-considerations-for.html' title='Performance Considerations for Recursive Calculations in MDX'/><author><name>Jeffrey Wang</name><uri>http://www.blogger.com/profile/09745744072887789758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-Di1-XjkHVCk/Tbh-m1UsFuI/AAAAAAAAABg/LZ7qT5hkDvo/s72-c/Query5.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8486191632104654344.post-3117735262396746823</id><published>2011-03-21T23:59:00.000-07:00</published><updated>2011-03-22T10:46:07.600-07:00</updated><title type='text'>The Logic behind the Magic of DAX Cross Table Filtering</title><content type='html'>&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Automatic cross filtering between columns of the same table or related tables is a very powerful feature of DAX. It allows a measure to evaluate to different values for different cells in a pivot table even though the DAX expression for the measure does not change. Filter context is the underlying mechanism that enables this magic behavior. But it is also a very tricky concept that even befuddles some DAX experts. &lt;a href="http://sqlblog.com/blogs/marco_russo"&gt;Marco Russo&lt;/a&gt; and &lt;a href="http://sqlblog.com/blogs/alberto_ferrari"&gt;Alberto Ferrari&lt;/a&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt; have introduced DAX filter context in Chapter 6 of their book &lt;i style="mso-bidi-font-style: normal;"&gt;Microsoft PowerPivot for Excel 2010&lt;/i&gt;. Marco has also blogged about &lt;a href="http://sqlblog.com/blogs/marco_russo/archive/2010/01/03/how-calculate-works-in-dax.aspx"&gt;how Calculate function works&lt;/a&gt;. Recently I have run into many questions from advanced DAX users which tell me that people are still confused about how filter context works exactly. And this will be the subject of today’s post. &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;This post assumes that you already have basic knowledge about measures, row context, filter context, and DAX functions Calculate, Values, All, etc.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;A level 200 pop quiz on DAX&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;If you think you already know how filter context works, let me ask you a couple of level 200 questions on DAX to see if you can explain the nuances of some DAX expressions. If you don’t feel like being challenged now, it is still beneficial to read the questions so you have some examples to better understand the following sections. The questions are based on the data model inside the publicly available sample PowerPivot workbook &lt;i style="mso-bidi-font-style: normal;"&gt;&lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=1ae63bfb-c303-44e3-ae44-7413d499495d"&gt;Contoso Samples DAX Formulas.xlsx&lt;/a&gt;&lt;/i&gt;. You can download the sample workbook to try out the formulas yourself if you want to, but it is not required to answer the questions.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;Question #1&lt;/b&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;People have heard that fact tables are automatically filtered by slices on dimension tables, but not the other way around, or in more general terms, if there is a relationship from table A to table B, A is automatically filtered by any slices on columns of B but B is not automatically filtered by any slices on columns of A. So if you select&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;DimProductSubcategory[ProductSubcategoryName] = “Air Conditioners” &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;on a pivot table slicer, measure&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;CountRows(DimProduct)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;returns 62 as DimProduct is limited to air conditioners. On the other hand, if you select&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;DimProduct[ProductLabel] = “0101001”,&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;measure&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;CountRows(DimProductSubcategory)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;returns 44 instead of just 1 although only a single product is selected. To filter DimProductSubcategory by the selected product label, you can define a measure as&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(CountRows(DimProductSubcategory), DimProduct)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;which returns 1. So it seems like when you explicitly add DimProduct as a setfilter argument of Calculate, DimProductSubcategory will be filtered by DimProduct. But if I define a measure as&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(CountRows(DimProductSubcategory), Values(DimProduct[ProductLabel])) &lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;to explicitly add the column that I know having a slice from the pivot table to the Calculate function , the measure formula returns 44 again. So what makes setfilter expression DimProduct work but Values(DimProduct[ProductLabel]) not work even though the filter only comes from [ProductLabel] column? If you think you have to add foreign key DimProduct[ProductSubcategoryKey] to the filter context in order for DimProductSubcategory to be filtered by DimProduct, you can try&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(CountRows(DimProductSubcategory), Values(DimProduct[ProductSubcategoryKey]))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;but it still returns 44. If you have enough patience, you can use Values function to explicitly add all 33 columns in DimProduct one by one as setfilter arguments to Calculate function and you still will get 44 back. So what is the difference between table expression DimProduct and the enumeration of all 33 columns in that table?&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;Question #2&lt;/b&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;There are 2556 records in DimDate table, therefore if you add a measure with expression&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;CountRows(DimDate)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;to a pivot table without any filters, the measure value would be 2556. Now if you add a second measure with expression&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(CountRows(DimDate), FactSales)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;to the same pivot table, the measure value would be 1096 since DimDate table is filtered by FactSales table and only dates with sales records are included. But if you add a third measure with expression&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(CountRows(DimDate), All(FactSales))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;to the pivot table, the measure value becomes 2556 again. Since this pivot table has no filters anywhere, shouldn’t FactSales and All(FactSales) return the same table? Now add a fourth measure with expression&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(CountRows(DimDate), Filter(All(FactSales), true))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;to the pivot table, the measure value becomes 1096 again. All three setfilter arguments return exactly the same table, why would we get back different results?&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;With these questions in mind, let’s examine the logic foundation upon which the magic world of DAX is built. At the end of the post, you will be able to find a logical explanation to all these seemingly inconsistent results.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;The expanded view of a DAX base table&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The best way to understand DAX cross table filtering is to think of each base table as extended by its related tables. When a relationship is created from table A to table B, the new A, which is really A left outer join B, includes both columns of A and columns of B. So in DAX, a table reference FactSales really refers to &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;FastSales &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;LOJ DimProduct LOJ DimProductSubcategory LOJ DimProductCategory &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;LOJ DimStore LOJ DimGeography LOJ DimDate LOJ DimChannel LOJ DimPromotion,&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;where LOJ means left outer join. This interpretation makes it easy to understand some other DAX syntax. For example, in DAX expression&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Filter(FactSales, Related(DimProduct[ProductLabel]) &lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;= “0101001”), &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Related(DimProduct[ProductLabel]) &lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;refers to the value of column DimProduct[ProductLabel] &lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;in the extended FactSales table. As a second example, DAX expression&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;AllExcept(FactSales, DimProduct[ProductLabel])&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;returns a table with all columns of extended FactSales table except for column DimProduct[ProductLabel].&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh6.googleusercontent.com/-Fv3q3MZi5tw/TYhIALeN25I/AAAAAAAAAA0/U8yG2zLhMXY/s1600/ExpandedTableView.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" r6="true" src="https://lh6.googleusercontent.com/-Fv3q3MZi5tw/TYhIALeN25I/AAAAAAAAAA0/U8yG2zLhMXY/s1600/ExpandedTableView.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Build initial filter context&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;DAX filter context is a stack of tables. At the beginning, the stack is empty. Given a pivot table, a filter context is initially populated by adding slicers and page filters. For each cell in a pivot table, current members of row labels and column labels also add filters to filter context. Other pivot table operations like visual totals add to initial filter context as well but I will keep things simple here. At this point, we have set up an initial filter context in which the measure expression of the current cell is to be evaluated. &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Measure invocation&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;If SumOfSales is the name of a measure and Sum(Sales[Amount]) is its DAX formula, DAX expression&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;[SumOfSales]&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;is equivalent to&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(Sum(Sales[Amount]))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;and DAX expression&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;[SumOfSales](Date[Year] = 2001, Store[Country] = “USA”) &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;is equivalent to&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(Sum(Sales[Amount]), Date[Year] = 2001, Store[Country] = “USA”).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;So the syntax sugar which makes a measure name look like a function name is just a clever way to add tables to filter context before evaluating the expression associated with the measure. Since invoking a measure implicitly calls Calculate, from now on I’ll just focus on Calculate function as the same rules apply equally to measures.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Add tables to filter context&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate function performs the following operations:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraphCxSpFirst" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;1.&lt;/span&gt;&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;Create a new filter context by cloning the existing one.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;2.&lt;/span&gt;&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;Move current rows in the row context to the new&amp;nbsp;filter context one by one and apply blocking semantics against all&amp;nbsp;previous tables.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;3.&lt;/span&gt;&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Evaluate each setfilter argument in the old filter context and then&amp;nbsp;add&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt; setfilter tables to the new&amp;nbsp;filter context one by one and apply blocking semantics against all tables that exist in the new&amp;nbsp;filter context before the first setfilter table is added.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraphCxSpLast" style="margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;4.&lt;/span&gt;&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;Evaluate the first argument in the newly constructed filter context.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;If a new table is added to filter context and it has blocking semantics against some tables already in the filter context, the affected tables are checked one by one, all common columns with the new table are marked as blocked on the existing table.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Let’s look at an example. Assume the current filter context has two filters: one filter is Date[Year] = 2011, the other filter is Store[Country] = “Canada”. We want to evaluate the following expression in the context&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;AverageX(Distinct(Date[Month]), Calculate(Sum(Sales[Amount]), Store[Country] = “USA”)).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The first argument of AverageX sets a month in row context. &lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;When it comes to Calculate, it first removes the month from row context and adds it to filter context, it does not block anything since there is no [Month] column in existing filters. Next Calculate adds Store[Country] = “USA” to filter context which blocks existing filter Store[Country] = “Canada”. When Sum(Sales[Amount]) is evaluated, Sales table is filtered by the current month in 2011 and stores in USA.&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh5.googleusercontent.com/-f1HPNCfn7Kc/TYhIBoyyV-I/AAAAAAAAAA4/v0WxS32w_As/s1600/FilterContextOverwrite.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" r6="true" src="https://lh5.googleusercontent.com/-f1HPNCfn7Kc/TYhIBoyyV-I/AAAAAAAAAA4/v0WxS32w_As/s1600/FilterContextOverwrite.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Targets of filter context&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;After so much effort populating and modifying a filter context, when will the filters be applied? In DAX, the filters in a filter context apply to following DAX table expressions:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraphCxSpFirst" style="margin: 0in 0in 0pt 0.5in; mso-list: l1 level1 lfo2; text-indent: -0.25in;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;1.&lt;/span&gt;&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;A table expression that is simply a table reference, such as FactSales.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraphCxSpMiddle" style="margin: 0in 0in 0pt 0.5in; mso-list: l1 level1 lfo2; text-indent: -0.25in;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;2.&lt;/span&gt;&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;Values(Table[Column]).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraphCxSpLast" style="margin: 0in 0in 10pt 0.5in; mso-list: l1 level1 lfo2; text-indent: -0.25in;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;3.&lt;/span&gt;&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;Distinct(Table[Column]).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;In cases of 2 and 3, the Table is filtered by filter context and then distinct values of [Column] are extracted from the filtered table.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;So if your expression is&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(SumX(Filter(FactSales, [SalesQuantity] &amp;gt; 1000), [SalesAmount]), Date[Year] = 2011),&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;the filter context only restricts FactSales and has no effect whatsoever on other parts of the formula. If you image every DAX formula is represented as a tree of parent and child function calls, a filter context is built at the top or in the middle of the tree but takes effect at leaf level table nodes.&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-p24kgXXYYzg/TYhH-3U_eTI/AAAAAAAAAAw/33mrY3wghGg/s1600/ApplyToLeaf.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" r6="true" src="https://lh3.googleusercontent.com/-p24kgXXYYzg/TYhH-3U_eTI/AAAAAAAAAAw/33mrY3wghGg/s1600/ApplyToLeaf.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Note that DAX function Sum(T[C]) is just a shorthand for SumX(T, [C]), the same is true for other aggregation functions which take a single column reference as argument. Therefore the table in those aggregation functions is filtered by filter context.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Apply filters to a target table&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Finally we have identified a target table and are ready to apply filters from filter context. For each filter table in the filter context, we check to see if there are any common columns between the target table and the unblocked columns of the filter table. If there is at least one common column, the target table is semi-joined with the filter table, or in SQL-like terms&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;SELECT * &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;FROM TargetTable AS t&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;WHERE EXISTS &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;(&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;SELECT * &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;FROM FilterTable AS f &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;WHERE t.CommonColumns = f.CommonColumns &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Each filter table is applied to the target table independently, so the target table is filtered by all relevant filters.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;All, AllExcept, AllNoBlankRow&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;So far I have said that each setfilter argument of Calculate function returns a table which is added to filter context. Well, that is true as long as the setfilter is not one of the All functions. The All functions should really be renamed as BlockColumns when they are used as setfilter arguments. If one of the All functions is used as the top-level function of setfilter, it &lt;b style="mso-bidi-font-weight: normal;"&gt;only&lt;/b&gt; blocks common columns of earlier tables but does &lt;b style="mso-bidi-font-weight: normal;"&gt;not&lt;/b&gt; add itself to filter context.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;In all other places, including as a sub-expression of a setfilter but not at the top level, All functions behave like any other DAX table expressions and always return a table. One special feature of All functions is that the Table argument inside All(Table), All(Table[Column]), AllExcept(Table, …), AllNoBlankRow(Table), etc. is not filtered by the current filter context.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Pop quiz answers&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;Answer to question #1&lt;/b&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;When the initial filter context contains column DimProduct[ProductLabel], table DimProductSubcategory is not filtered as it does not have that column. &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Now look at the next formula&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(CountRows(DimProductSubcategory), DimProduct).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The setfilter argument DimProduct is filtered by [ProductLabel], and then table DimProductSubcategory is filtered by table DimProduct since they both share the columns from table DimProductSubcategory and table DimProductCategory.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Move onto the next two formulas&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(CountRows(DimProductSubcategory), Values(DimProduct[ProductLabel]))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(CountRows(DimProductSubcategory), Values(DimProduct[ProductSubcategoryKey]))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Both setfilter arguments are a single column table and the column comes from table DimProduct. Since table DimProductSubcategory does not have any column from DimProduct, it is not filtered by filter context. For the same reason, you can add any columns from DimProduct to the filter context and none of them would impact DimProductSubcategory.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;Answer to question #2&lt;/b&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;In the first formula&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(CountRows(DimDate), FactSales)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Both table DimDate and table FactSales share columns from DimDate, so DimDate is filtered by FactSales.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;In the second formula&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(CountRows(DimDate), All(FactSales))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;All(FactSales) blocks any columns from FactSales, but since the filter context is empty, it has no effect. When DimDate is evaluated, filter context is still empty.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;In the third formula&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;Calculate(CountRows(DimDate), Filter(All(FactSales), true))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The All function is not at the top level of setfilter argument, table Filter(All(FactSales), true) is added to filter context, table DimDate is filtered by filter context for the same reason as in the first formula.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8486191632104654344-3117735262396746823?l=mdxdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdxdax.blogspot.com/feeds/3117735262396746823/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mdxdax.blogspot.com/2011/03/logic-behind-magic-of-dax-cross-table.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/3117735262396746823'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/3117735262396746823'/><link rel='alternate' type='text/html' href='http://mdxdax.blogspot.com/2011/03/logic-behind-magic-of-dax-cross-table.html' title='The Logic behind the Magic of DAX Cross Table Filtering'/><author><name>Jeffrey Wang</name><uri>http://www.blogger.com/profile/09745744072887789758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh6.googleusercontent.com/-Fv3q3MZi5tw/TYhIALeN25I/AAAAAAAAAA0/U8yG2zLhMXY/s72-c/ExpandedTableView.gif' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8486191632104654344.post-6056390966775622796</id><published>2011-02-22T20:58:00.000-08:00</published><updated>2011-03-04T17:00:36.881-08:00</updated><title type='text'>MDX Overwrite Semantics and Complex Attribute Relationship</title><content type='html'>&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The past month has been extremely busy for me so I didn’t get to write more blogs. Today we’ll resume the exploration of MDX calculation engine. In this post I am going to describe a common mistake made by people when writing MDX calculations that can be very hard to diagnose.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Calibri;"&gt;WARNING: The MDX overwrite behavior I am going to describe in this post applies to overwriting to a physical member or the [All] member. Overwriting to a calculated member has its own set of rules which are not covered here.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;An Example&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Let’s start with a simple example using Adventure Works DW 2008 database. First create a calculated measure, [m], that returns [Internet Sales Amount] for the first quarter of fiscal year 2004.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="color: blue; font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;create&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt; &lt;span style="color: blue;"&gt;member&lt;/span&gt; [Adventure Works].[Measures].[m] &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;([Internet Sales Amount], [Date].[Fiscal].[Fiscal Quarter].[Q1 FY 2004])&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Next send a query to check the value of [m].&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt 0.5in; mso-layout-grid-align: none;"&gt;&lt;span style="color: blue; font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;select&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt; [m] &lt;span style="color: blue;"&gt;on&lt;/span&gt; 0&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="color: blue; font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; line-height: 115%; mso-no-proof: yes;"&gt;from&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; line-height: 115%; mso-no-proof: yes;"&gt; [Adventure Works]&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-bottom: medium none; border-collapse: collapse; border-left: medium none; border-right: medium none; border-top: medium none; margin: auto auto auto 0.5in; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-yfti-tbllook: 1184;"&gt;&lt;tbody&gt;&lt;tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;m&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 1; mso-yfti-lastrow: yes;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;$2,744,340.48&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Now send another query calculating [m] but start with different calendar quarters.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt 0.5in; mso-layout-grid-align: none;"&gt;&lt;span style="color: blue; font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;select&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt; [m] &lt;span style="color: blue;"&gt;on&lt;/span&gt; 0,&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt 0.5in; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;[Date].[Calendar].[Calendar Quarter].&lt;span style="color: blue;"&gt;members&lt;/span&gt; &lt;span style="color: blue;"&gt;on&lt;/span&gt; 1&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="color: blue; font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; line-height: 115%; mso-no-proof: yes;"&gt;from&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; line-height: 115%; mso-no-proof: yes;"&gt; [Adventure Works]&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-bottom: medium none; border-collapse: collapse; border-left: medium none; border-right: medium none; border-top: medium none; margin: auto auto auto 0.5in; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-yfti-tbllook: 1184;"&gt;&lt;tbody&gt;&lt;tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;m&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 1;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Q3 CY 2001&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;(null)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 2;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Q4 CY 2001&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;(null)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 3;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Q1 CY 2002&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;(null)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 4;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Q2 CY 2002&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;(null)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 5;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Q3 CY 2002&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;(null)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 6;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Q4 CY 2002&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;(null)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 7;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Q1 CY 2003&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;(null)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 8;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Q2 CY 2003&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;(null)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 9;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Q3 CY 2003&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;$2,744,340.48&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 10;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Q4 CY 2003&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;(null)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 11;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Q1 CY 2004&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;(null)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 12;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Q2 CY 2004&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;(null)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 13;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Q3 CY 2004&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;(null)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 14; mso-yfti-lastrow: yes;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 77.4pt;" valign="top" width="103"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Q4 CY 2006&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 85.5pt;" valign="top" width="114"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;(null)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Why don’t we see the value, $2,744,340.48, in all cells? Didn’t the MDX formula of [m] change whatever calendar quarter to the first quarter of fiscal year 2004? The answer lies in MDX overwrite semantics and attribute relationship of the [Date] dimension.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Examine&amp;nbsp;the Example Based on MDX Overwrite Rules&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Before we delve into details, let’s establish some terminologies first. MDX attribute relationship defines functional dependency between two attributes, e.g. &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;[Calendar Quarter] &lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;→&lt;/span&gt; [Calendar Semester] &lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;→ [Calendar Year].&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;If A &lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;→&lt;/span&gt; B, we say B is &lt;b style="mso-bidi-font-weight: normal;"&gt;related&lt;/b&gt; to A and A is &lt;b style="mso-bidi-font-weight: normal;"&gt;relating&lt;/b&gt; to B. Therefore, [Calendar Semester] and [Calendar Year] are related attributes of [Calendar Quarter], and reversely [Calendar Quarter] and [Calendar Semester] are relating attributes of [Calendar Year]. &lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&lt;/span&gt;On the other hand, [Fiscal Week] and [Calendar Quarter] are not related to each other.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Every MDX expression is evaluated in a context. In a simple case, the context includes the current cell which is defined by the current coordinates of all attributes in the cube. When an MDX expression, like ([Internet Sales Amount], [Date].[Calendar Year].[CY 2004]), overwrites the coordinates of some attributes to &lt;b style="mso-bidi-font-weight: normal;"&gt;non-All&lt;/b&gt; members, it also &lt;u&gt;overwrites the coordinates of all related and relating attributes&lt;/u&gt;. The following diagram illustrates how MDX overwrite semantics work when you set non-All slices to some attributes.&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-YjZ_c4wJil0/TWSRk62GKII/AAAAAAAAAAQ/kUs5XXAdJ0c/s1600/P1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="433" j6="true" src="http://4.bp.blogspot.com/-YjZ_c4wJil0/TWSRk62GKII/AAAAAAAAAAQ/kUs5XXAdJ0c/s640/P1.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The common mistake I referred to at the beginning of the post is when people forget about the slices left over at the unrelated attributes. When dimension autoexists is applied and the new slices set by the MDX expression do not exist with the slices left over on the unrelated attributes, you end up with cells that don’t exist. Note that we don’t have this problem when there is only a simple linear attribute relationship defined on the dimension.&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-LvMlFMPli_M/TWSRvAuWwWI/AAAAAAAAAAU/89eNLgErIqI/s1600/P2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" j6="true" src="http://4.bp.blogspot.com/-LvMlFMPli_M/TWSRvAuWwWI/AAAAAAAAAAU/89eNLgErIqI/s320/P2.png" width="218" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt 2in;"&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;In case of a single linear relationship, all attributes in the dimension are always overwritten, either explicitly or implicitly, when any attribute is set to a non-All member. The problem arises only when there is a complex attribute relationship, one with tree-like structure.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Going to back to the Adventure Works example, to calculate the value of any cell, an initial cell coordinate is set to a quarter from the [Calendar] hierarchy. Moreover, all related and relating attributes are set implicitly as well. See a simplified version of attribute relationship below. Every attribute in the diagram, except for [Month Name] is set to a slice that corresponds to a calendar quarter.&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh4.googleusercontent.com/-lLAkfwOdss4/TXGKJiI8lgI/AAAAAAAAAAo/Q6CnIlMpQ4k/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="329" l6="true" src="https://lh4.googleusercontent.com/-lLAkfwOdss4/TXGKJiI8lgI/AAAAAAAAAAo/Q6CnIlMpQ4k/s640/1.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;shape id="_x0000_i1025" o:ole="" style="height: 147pt; width: 468pt;" type="#_x0000_t75"&gt;&lt;imagedata o:title="" src="file:///C:\Users\jewang\AppData\Local\Temp\msohtmlclip1\01\clip_image004.emz"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;/span&gt;&lt;/imagedata&gt;&lt;/shape&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;After applying the MDX expression associated with calculated measure [m], some attribute slices change to new ones, shown as colored boxes below, other attribute slices retain the previous values, shown as white boxes below.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;shape id="_x0000_i1026" o:ole="" style="height: 209.25pt; width: 468pt;" type="#_x0000_t75"&gt;&lt;imagedata o:title="" src="file:///C:\Users\jewang\AppData\Local\Temp\msohtmlclip1\01\clip_image006.emz"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;/span&gt;&lt;/imagedata&gt;&lt;/shape&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://lh3.googleusercontent.com/-51INzxnRPcg/TXGKLD6dIYI/AAAAAAAAAAs/AN6GQQ63Z4k/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="330" l6="true" src="https://lh3.googleusercontent.com/-51INzxnRPcg/TXGKLD6dIYI/AAAAAAAAAAs/AN6GQQ63Z4k/s640/2.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="font-family: Calibri;"&gt;You get a valid new cell only when the new slices correspond to the first quarter of fiscal year 2004 exist with the untouched old slices derived from the original calendar quarter; otherwise you get a cell that doesn’t exist hence a NULL value for the MDX formula. In this case only the third quarter of calendar year 2003 produces valid cell coordinates. To force setting the current coordinate to the first quarter of fiscal year 2004 regardless of the current calendar quarter, you have to explicitly overwrite all attributes related to the [Calendar] hierarchy like below:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt 0.5in; mso-layout-grid-align: none;"&gt;&lt;span style="color: blue; font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;create&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt; &lt;span style="color: blue;"&gt;member&lt;/span&gt; [Adventure Works].[Measures].[m] &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt 0.5in; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;(&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt 0.5in; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[Internet Sales Amount], &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt 0.5in; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[Date].[Fiscal].[Fiscal Quarter].[Q1 FY 2004],&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt 0.5in; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[Date].[Calendar].[All]&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt 0.5in; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Official Rules&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The above example is based on overwriting the current coordinate to a non-All member. But what about the other cases? Well, the following table lists all combinations of how overwriting one attribute can affect its related or relating attributes.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Assume A &lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;→&lt;/span&gt; B.&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-bottom: medium none; border-collapse: collapse; border-left: medium none; border-right: medium none; border-top: medium none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-yfti-tbllook: 480;"&gt;&lt;tbody&gt;&lt;tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 149.4pt;" valign="top" width="199"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="font-family: Calibri;"&gt;Explicit Overwrite&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 193.5pt;" valign="top" width="258"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="font-family: Calibri;"&gt;Result&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 1;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 149.4pt;" valign="top" width="199"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="font-family: Calibri;"&gt;A.All to A.All&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 193.5pt;" valign="top" width="258"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="font-family: Calibri;"&gt;B unaffected&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 2;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 149.4pt;" valign="top" width="199"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="font-family: Calibri;"&gt;A.x to A.All&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 193.5pt;" valign="top" width="258"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="font-family: Calibri;"&gt;B to B.All&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 3;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 149.4pt;" valign="top" width="199"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="font-family: Calibri;"&gt;A to A.x&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 193.5pt;" valign="top" width="258"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="font-family: Calibri;"&gt;B to Exists(B.members, A.x)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 4;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 149.4pt;" valign="top" width="199"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="font-family: Calibri;"&gt;B.All to B.All&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 193.5pt;" valign="top" width="258"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="font-family: Calibri;"&gt;A to A.All&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 5;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 149.4pt;" valign="top" width="199"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="font-family: Calibri;"&gt;B.x to B.All&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 193.5pt;" valign="top" width="258"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="font-family: Calibri;"&gt;A to A.All&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 6; mso-yfti-lastrow: yes;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 149.4pt;" valign="top" width="199"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="font-family: Calibri;"&gt;B to B.x&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 193.5pt;" valign="top" width="258"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="font-family: Calibri;"&gt;A to A.All&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;An implicit overwrite is when an attribute is moved because of an overwrite on a relating or related attribute. When an attribute is impacted by both an explicit overwrite and an implicit overwrite, the explicit takes precedence. Implicit overwrites do not overwrite related or relating attributes.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Parent Child Dimension&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;According to the overwrite rules discussed so far, overwriting the key attribute of a dimension to a non-All member should overwrite all other attributes in the dimension implicitly. But this does not work for parent child dimensions.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;If you run query&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="color: blue; font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;with&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt; &lt;span style="color: blue;"&gt;member&lt;/span&gt; measures.x &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;(&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[Measures].[Amount], &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[Account].[Account].[Work in Process]&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="color: blue; font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;select&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt; x &lt;span style="color: blue;"&gt;on&lt;/span&gt; 0,&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;([Account].[Account].[Raw Materials], [Account].[Account Number].[1162]) &lt;span style="color: blue;"&gt;on&lt;/span&gt; 1&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="color: blue; font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; line-height: 115%; mso-no-proof: yes;"&gt;from&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; line-height: 115%; mso-no-proof: yes;"&gt; [Adventure Works]&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-bottom: medium none; border-collapse: collapse; border-left: medium none; border-right: medium none; border-top: medium none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-yfti-tbllook: 1184;"&gt;&lt;tbody&gt;&lt;tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 81.9pt;" valign="top" width="109"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 49.5pt;" valign="top" width="66"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 49.5pt;" valign="top" width="66"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;x&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 1; mso-yfti-lastrow: yes;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 81.9pt;" valign="top" width="109"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Raw Materials&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 49.5pt;" valign="top" width="66"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;1162&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 49.5pt;" valign="top" width="66"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;(null)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;You get back null result even though the calculation overwrites the key attribute [Account]. You have to explicitly overwrite [Account Number] attribute to get back the [Amount] for [Work in Process].&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="color: blue; font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;with&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt; &lt;span style="color: blue;"&gt;member&lt;/span&gt; measures.x &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;(&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[Measures].[Amount], &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[Account].[Account].[Work in Process], &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[Account].[Account Number].[All]&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="color: blue; font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;select&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt; x &lt;span style="color: blue;"&gt;on&lt;/span&gt; 0,&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; mso-no-proof: yes;"&gt;([Account].[Account].[Raw Materials], [Account].[Account Number].[1162]) &lt;span style="color: blue;"&gt;on&lt;/span&gt; 1&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="color: blue; font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; line-height: 115%; mso-no-proof: yes;"&gt;from&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;; font-size: 10pt; line-height: 115%; mso-no-proof: yes;"&gt; [Adventure Works]&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-bottom: medium none; border-collapse: collapse; border-left: medium none; border-right: medium none; border-top: medium none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-yfti-tbllook: 1184;"&gt;&lt;tbody&gt;&lt;tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 81.9pt;" valign="top" width="109"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 49.5pt;" valign="top" width="66"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 81pt;" valign="top" width="108"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;x&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 1; mso-yfti-lastrow: yes;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 81.9pt;" valign="top" width="109"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Raw Materials&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 49.5pt;" valign="top" width="66"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;1162&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 81pt;" valign="top" width="108"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;$1,393,582.00&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The official rule here is that:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Overwriting key attribute of parent child hierarchy does not overwrite other attributes except that of its parent.&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-7DdFGpuG3Tk/TWSTMytP2oI/AAAAAAAAAAg/Jl8DZklbKuw/s1600/P3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="304" j6="true" src="http://3.bp.blogspot.com/-7DdFGpuG3Tk/TWSTMytP2oI/AAAAAAAAAAg/Jl8DZklbKuw/s640/P3.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;shape id="Picture_x0020_29" o:spid="_x0000_i1028" style="height: 223.5pt; mso-wrap-style: square; visibility: visible; width: 468pt;" type="#_x0000_t75"&gt;&lt;imagedata o:title="" src="file:///C:\Users\jewang\AppData\Local\Temp\msohtmlclip1\01\clip_image008.png"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;/span&gt;&lt;/imagedata&gt;&lt;/shape&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Complex Relationships Are Very Common&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Unless you define a single linear relationship for a dimension, you will end up with a complex relationship. Specifically, when there are more than two attributes in a dimension and you didn’t define any relationship, the default one is a tree-like relationship.&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-hyWBtA4P0tg/TWSTT3986dI/AAAAAAAAAAk/80jzPQMb4SI/s1600/P4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="120" j6="true" src="http://2.bp.blogspot.com/-hyWBtA4P0tg/TWSTT3986dI/AAAAAAAAAAk/80jzPQMb4SI/s400/P4.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="mso-no-proof: yes;"&gt;&lt;shape id="Picture_x0020_28" o:spid="_x0000_i1027" style="height: 103.5pt; mso-wrap-style: square; visibility: visible; width: 338.25pt;" type="#_x0000_t75"&gt;&lt;imagedata o:title="" src="file:///C:\Users\jewang\AppData\Local\Temp\msohtmlclip1\01\clip_image010.png"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;/span&gt;&lt;/imagedata&gt;&lt;/shape&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;MDX Writeback with Custom Weight Expression&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Users are likely to make the mistake we have discussed so far when the current cell coordinates contain many slices on numerous attributes. This is particularly true when it comes to MDX writeback with custom weight expression. When an MDX UPDATE CUBE statement is sent to Analysis Services, the desired result is allocated to leaf level nodes. So if you are writing a custom weight formula, the current context is always a leaf level cell with a slice on every regular attribute. If you are not careful overwriting all attributes in a dimension, your weight expression is likely to return NULL values and you won’t get the allocation you desired.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 12pt; line-height: 115%; mso-bidi-font-size: 11.0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Conclusion&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The complex rules of MDX overwrite semantics combined with a tree-like attribute relationship can easily lead to some very frustrating bugs in your MDX formula. You must make sure to overwrite slices on all attributes you don’t want to&amp;nbsp;keep and preserve the slices on all attributes you do want to keep. Remember that the rules are different for parent child dimensions. If you have a simple tuple like MDX formula that returns unexpected NULLs, you should check whether you have violated the guidelines given in this blog post.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8486191632104654344-6056390966775622796?l=mdxdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdxdax.blogspot.com/feeds/6056390966775622796/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mdxdax.blogspot.com/2011/02/mdx-overwrite-semantics-and-complex.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/6056390966775622796'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/6056390966775622796'/><link rel='alternate' type='text/html' href='http://mdxdax.blogspot.com/2011/02/mdx-overwrite-semantics-and-complex.html' title='MDX Overwrite Semantics and Complex Attribute Relationship'/><author><name>Jeffrey Wang</name><uri>http://www.blogger.com/profile/09745744072887789758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-YjZ_c4wJil0/TWSRk62GKII/AAAAAAAAAAQ/kUs5XXAdJ0c/s72-c/P1.png' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8486191632104654344.post-7471708140894834358</id><published>2011-01-17T16:33:00.000-08:00</published><updated>2011-02-27T23:29:19.477-08:00</updated><title type='text'>DAX Time Intelligence Functions</title><content type='html'>&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Time intelligence functions are an advanced feature of DAX. They are typically composite functions built on top of other more basic DAX features and have more stringent requirements for the structure of the underlying database. But since time related calculations are fundamental to almost all BI projects, early adopters of DAX&amp;nbsp;started using&amp;nbsp;the time intelligence functions almost immediately after the first release of DAX. Due to the advanced nature of these functions, questions naturally arise about how they work and why they work that way even when people managed to get the desired results.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Marius Dumitru, architect of AS engine team, gave the following recipe to users of time intelligence functions.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;1.&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Never use the datetime column from the fact table in time functions.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;2.&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Always create a separate Time table with contiguous dates (i.e. without missing day gaps in the date values).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;3.&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Create relationships between fact tables and the Time table.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;4.&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Make sure that relationships are based on a datetime column (and NOT based on another artificial key column).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;5.&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Make sure you have full years’ worth of data in the Time table. For instance, even though your transaction table may only have sales data up to May 2010, the Time table should have dates up to December 2010 (same goes for fiscal years).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;6.&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;The datetime column in the Time table should be at day granularity (without fractions of a day).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;In this post, I’ll expose more details behind the implementation of time intelligence functions to shed light on the rationale behind Marius’ advice. This post is meant to supplement online documentation of SQL Server 2008 R2. I will &lt;u&gt;not&lt;/u&gt; cover basic usage examples of time intelligence functions in typical BI applications. DAX is a young functional language that evolves rapidly. What is covered here applies to SQL Server 2008 R2.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;I assume you are already familiar with advanced DAX concepts such as row context, filter context, Calculate function, Values function, measures, etc. I’ll start with some common features across all time intelligence functions before I delve into individual functions.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 14pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The &amp;lt;dates&amp;gt; argument&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;All time intelligence functions have a special &amp;lt;dates&amp;gt; argument. FirstNonBlank and LastNonBlank operate on non-date/time columns but the conversion rules descibed below still apply. With the exception of DatesBetween and DatesInPeriod, the &amp;lt;dates&amp;gt; argument can be one of three forms:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraphCxSpFirst" style="line-height: normal; margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;1.&lt;/span&gt;&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;A reference to a date/time column.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraphCxSpMiddle" style="line-height: normal; margin: 0in 0in 0pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;2.&lt;/span&gt;&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;A table expression that returns a single column of date/time values.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoListParagraphCxSpLast" style="line-height: normal; margin: 0in 0in 10pt 0.5in; mso-list: l0 level1 lfo1; text-indent: -0.25in;"&gt;&lt;span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-family: Calibri;"&gt;3.&lt;/span&gt;&lt;span style="font-family: &amp;quot;Times New Roman&amp;quot;;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt;A boolean expression that defines a single-column table of date/time values.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Internally, all three forms are converted to a DAX table expression in the following fashion:&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;/div&gt;&lt;table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-bottom: medium none; border-collapse: collapse; border-left: medium none; border-right: medium none; border-top: medium none; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0in 5.4pt 0in 5.4pt; mso-yfti-tbllook: 1184;"&gt;&lt;tbody&gt;&lt;tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 90.9pt;" valign="top" width="121"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Format number&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 196.4pt;" valign="top" width="262"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;&amp;lt;dates&amp;gt; format&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: windowtext 1pt solid; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 191.5pt;" valign="top" width="255"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;Internal table expression&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 1;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 90.9pt;" valign="top" width="121"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 196.4pt;" valign="top" width="262"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;T[C]&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 191.5pt;" valign="top" width="255"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;CalculateTable(Values(T[C]))&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 2;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 90.9pt;" valign="top" width="121"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;2&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 196.4pt;" valign="top" width="262"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Single column table expression&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 191.5pt;" valign="top" width="255"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;As is&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr style="mso-yfti-irow: 3; mso-yfti-lastrow: yes;"&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: windowtext 1pt solid; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 90.9pt;" valign="top" width="121"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 196.4pt;" valign="top" width="262"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Well-formed scalar expression&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;td style="background-color: transparent; border-bottom: windowtext 1pt solid; border-left: #f0f0f0; border-right: windowtext 1pt solid; border-top: #f0f0f0; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt; padding-bottom: 0in; padding-left: 5.4pt; padding-right: 5.4pt; padding-top: 0in; width: 191.5pt;" valign="top" width="255"&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 0pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Filter(All(T[C]), &amp;lt;scalar expression&amp;gt;)&lt;/span&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;span style="font-family: Calibri;"&gt;What is a well-formed scalar expression? Vaguely speaking, it is a scalar expression that DAX engine can analyze and extract a fully qualified column reference to a date/time column. &lt;i style="mso-bidi-font-style: normal;"&gt;T[C] = Date(2011, 1, 17)&lt;/i&gt; is a well-formed expression as DAX engine can extract T[C] from it. &lt;i style="mso-bidi-font-style: normal;"&gt;T[C] * 2&lt;/i&gt; is a well-formed expression for the same reason even though it is not a boolean expression DAX engine will cast it to boolean data type implicitly. &lt;i style="mso-bidi-font-style: normal;"&gt;Date(2011, 1, 17)&lt;/i&gt; is not a well-formed scalar expression as no column reference can be extracted from it.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Note that internally inserted CalculateTable in the first format automatically converts current row contexts to filter contexts. So&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt; text-indent: 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;MaxX(Distinct(DimDate[CalendarYear]), OpeningBalanceYear([m], DimDate[Datekey]))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;will give the maximum opening balance among all years, but&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;MaxX(Distinct(DimDate[CalendarYear]), OpeningBalanceYear([m], Values(DimDate[Datekey])))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;will not as the &amp;lt;dates&amp;gt; argument is in the second format hence not correlated to the current calendar year on the row context.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 14pt;"&gt;&lt;span style="font-family: Calibri;"&gt;A special rule regarding datetime filter inside Calculate/CalculateTable &lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;If a Calculate filter has a unique column that is of data type date/time, all previous filters on all columns from the table which contains this date/time column are removed. This hacky feature implies that&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;Calculate(&amp;lt;expression&amp;gt;, &amp;lt;TI function&amp;gt;) = Calculate(&amp;lt;expression&amp;gt;, &amp;lt;TI function&amp;gt;, All(DateTable)).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;This is the reason behind Marius’ recommendation #4. Let’s say you have some years on the pivot-table row and then you drag a measure which uses time-intelligence function DateAdd to show sales from the previous year. The author of the measure formula may not realize that DateAdd function only returns a single column of Datekey which overwrites existing filter on the same column. This special rule makes sure that the filter on the CalendarYear column, which comes from the pivot-table, is also removed so you get back the expected result. Without this special rule, Calculate(&amp;lt;expression&amp;gt;, &amp;lt;TI function&amp;gt;) would set days of the previous year on the Datekey column but leave the previous year as the filter on the CalendarYear column. The conflicting filters would have produced a blank result.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;In PowerPivot v1, the only way to mark a column as unique is to create an incoming relationship to this column, hence Marius’ recommendation #3. You obviously also need a separate Date table in order to create a relationship.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;In practice, people want to use integer keys to create relationship between Fact table and Date table. If you want to use time intelligence functions in that case, you must add All(DateTable) filter yourself to the measure expression.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;In future versions of PowerPivot, users may be able to mark a date/time column as unique without creating an incoming relationship to the column. When that happens, recommendation #3 would no longer be needed.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 14pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Calendar&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;DAX engine creates an internal calendar data structure for each date/time column used in the time intelligence functions. The calendar contains a hierarchy of year-quarter-month-day. The minimum year and the maximum year in the calendar are determined by the actual dates in the date/time column. Internally, intermediate results are represented as arrays of days. So to represent January 2011, intermediate result would hold the 31 days in that month. Although a calendar contains all days in the years involved, it marks which days actually exist in the column. Calendar member functions return result days only if they are marked as exists. So if you have missing dates in the date/time column, they cannot be returned as a result of time intelligence functions.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;When a calendar data structure is initially populated, it raises an error if two values from the date/time column correspond to the same day. So if you have a date/time column below the day granularity, it cannot be used in time intelligence functions.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Obviously calendar is an internal implementation detail which is subject to change in future releases of DAX. I mention it here to explain some of the limitations imposed on the current version of time intelligence functions. I’ll refer to calendar again when I discuss individual functions next.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 14pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Primitive time intelligence functions&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;As I mentioned at the beginning of the post, time intelligence functions are an advanced feature of DAX. They are built on top of other DAX features and functions, so there is nothing primitive about them. But many time-intelligence functions are composed from more basic time-intelligence functions which have their native implementations, I call the latter primitive ones.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;FirstDate/LastDate/StartOfMonth/EndOfMonth/StartOfQuarter/EndOfQuarter/StartOfYear/EndOfYear return a table of a single column and a single row. They can be used anywhere a table expression or a scalar expression is needed due to implicit table to scalar cast.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;As I described in the section on the &amp;lt;dates&amp;gt; argument, no matter which format the user uses, internally they are all converted to a table expression. From now on I will use &lt;b style="mso-bidi-font-weight: normal;"&gt;&amp;lt;dates table&amp;gt;&lt;/b&gt; to denote the table expression equivalent to &amp;lt;dates&amp;gt;. I will use &lt;b style="mso-bidi-font-weight: normal;"&gt;DimDate[Datekey] &lt;/b&gt;or simply&lt;b style="mso-bidi-font-weight: normal;"&gt; [Datekey]&lt;/b&gt; to denote the date/time column extracted from &amp;lt;dates&amp;gt; expression.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;FirstDate(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;LastDate(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;These two functions return a single column, single row table with values equivalent to&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;MinX(&amp;lt;dates table&amp;gt;, [Datekey]), or&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;MaxX(&amp;lt;dates table&amp;gt;, [Datekey]).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;FirstNonBlank(&amp;lt;column&amp;gt;, &amp;lt;expression&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;LastNonBlank(&amp;lt;column&amp;gt;, &amp;lt;expression&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;These two functions are not pure time-intelligence functions as the first&amp;nbsp;argument&amp;nbsp;is not limited to&amp;nbsp;&amp;lt;dates&amp;gt; as in all other time-intelligence functions.&amp;nbsp;They are internally rewritten as&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;Top1(Filter(&amp;lt;column table&amp;gt;, Not(IsBlank(&amp;lt;expression&amp;gt;)), [column]), and&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;Bottom1(Filter(&amp;lt;column table&amp;gt;, Not(IsBlank(&amp;lt;expression&amp;gt;)), [column]) respectively.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Top1 and Bottom1 are internal functions&amp;nbsp;similar to MinX and MaxX functions but support all DAX data types include boolean and string data types.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Calibri;"&gt;Note that &amp;lt;expression&amp;gt; is not automatically wrapped in Calculate, therefore,&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;FirstNonBlank(DimDate[Datekey], Sum(FactSales[SalesAmount]))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;does not give you what you want, but&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;FirstNonBlank(DimDate[Datekey], Calculate(Sum(FactSales[SalesAmount])))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;will produce the expected result.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;StartOfMonth(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;StartOfQuarter(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;StartOfYear(&amp;lt;dates&amp;gt;, &amp;lt;year_end_date&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Although not implemented this way, these functions first find FirstDate(&amp;lt;dates&amp;gt;), then jump to first day that exists in the same month/quarter/year.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;EndOfMonth(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;EndOfQuarter(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;EndOfYear(&amp;lt;dates&amp;gt;, &amp;lt;year_end_date&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Although not implemented this way, these functions first find LastDate(&amp;lt;dates&amp;gt;), then jump to the last day that exists in the same month/quarter/year.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;DateAdd(&amp;lt;dates&amp;gt;, &amp;lt;number_of_intervals&amp;gt;, &amp;lt;interval&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;ParallelPeriod(&amp;lt;dates&amp;gt;, &amp;lt;number_of_intervals&amp;gt;, &amp;lt;interval&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;SamePeriodLastYear(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;SamePeriodLastYear(&amp;lt;dates&amp;gt;) is identical to DateAdd(&amp;lt;dates&amp;gt;, -1, Year).&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Both DateAdd and ParallelPeriod invoke a function, Move, on the calendar object. The only difference is that ParallelPeriod requires the result days to fill an entire month/quarter/year, while DateAdd does not have this requirement. &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Currently, DateAdd has a limitation that &amp;lt;dates table&amp;gt; must contain continuous days so that the result days can be continuous too.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;We have this limitation because when you move all 28 days in February one month forward, like below, &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;DateAdd(filter(All(DimDate[Datekey]), Year([Datekey]) = 2006 &amp;amp;&amp;amp; Month([Datekey]) = 2), 1, Month)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;you get back 31 days in March! As we mentioned in the section about Calendar, all intermediate results of time intelligence functions are represented as an array of days. So there is no difference between all days in February and February itself. But what if you have one day missing in the middle of February? Should we return one day missing in March or 27 days in March? This seems to be a tricky but less important question, so we left it undecided and raised an error instead.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The calendar object’s Move function is the most &lt;i style="mso-bidi-font-style: normal;"&gt;intelligent&lt;/i&gt; part of all time intelligence functions. It knows that moving both 3/30 and 3/31 one month forward end up on the same day 4/30. Internally it only moves by number of days or months, number of quarters or years is simply translated to corresponding number of months. Sometimes the Move function can be too smart for the user. When it moves a continuous range of days forward N months, it checks the start day and the end day of the range to see if you are moving whole months or just individual days. This works well when all days exist in the date/time column. But if you have missing days, the Move logic still tries to guess whether you are moving whole months based on days that exist, this may not be what you would expect, hence Marius’ recommendation #2.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;DatesBetween(&amp;lt;dates&amp;gt;, &amp;lt;start_date&amp;gt;, &amp;lt;end_date&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;DatesInPeriod(&amp;lt;dates&amp;gt;, &amp;lt;start_date&amp;gt;, &amp;lt;number_of_intervals&amp;gt;, &amp;lt;interval&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;These two functions are different from the other time intelligence functions in that the &amp;lt;dates&amp;gt; argument can only be a fully-qualified column reference to a date/time column. Note that online document incorrectly states that the &amp;lt;dates&amp;gt; argument in DatesInPeriod can be any of the three formats.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Internally, both functions are rewritten as&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;Filter(All(DimDate[Datekey]), DatesRange([Datekey], Earlier(&amp;lt;start_date&amp;gt;), Earlier(&amp;lt;end_date&amp;gt;))) or&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;Filter(All(DimDate[Datekey]), DatesRange([Datekey], Earlier(&amp;lt;start_date&amp;gt;, Earlier(&amp;lt;number_of_intervals&amp;gt;), &amp;lt;interval&amp;gt;))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;In the formulas above, Earlier is an internal extended version of the public Earlier function that evaluates an entire DAX expression by skipping the last row context. DatesRange is an internal boolean function that returns true if the value of the first argument falls within an interval. In case of DatesRange(&amp;lt;date_value&amp;gt;, &amp;lt;start_date&amp;gt;, &amp;lt;end_date&amp;gt;), the interval is defined as [start_date, end_date]. In case of DatesRange(&amp;lt;date_value&amp;gt;, &amp;lt;start_date&amp;gt;, &amp;lt;number_of_intervals&amp;gt;, &amp;lt;interval&amp;gt;), the interval is defined as [start_date, end_date) where end_date is calculated by calling the Move function on the calendar object, so it is a smart move&lt;/span&gt;&lt;span style="font-family: Wingdings; mso-ascii-font-family: Calibri; mso-ascii-theme-font: minor-latin; mso-char-type: symbol; mso-hansi-font-family: Calibri; mso-hansi-theme-font: minor-latin; mso-symbol-font-family: Wingdings;"&gt;&lt;span style="mso-char-type: symbol; mso-symbol-font-family: Wingdings;"&gt;J&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Calibri;"&gt; Note that since &amp;lt;number_of_intervals&amp;gt; can be a negative number, like when you move backwards in time, the interval specified by DatesInPeriod can be in the reverse order. DatesBetween does &lt;u&gt;not&lt;/u&gt; allow reversed end points.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Also note that All(DimDate[Datekey]) implies that existing filter context does not apply to the date/time column, unlike when all other time intelligence functions use the name-pair syntax.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;PreviousDay(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;PreviousMonth(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;PreviousQuarter(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;PreviousYear(&amp;lt;dates&amp;gt;, &amp;lt;year_end_date&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Although not implemented this way, these function are equivalent to&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;FirstDate(DateAdd(&amp;lt;dates&amp;gt;, -1, Day)) in case of PreviousDay, or&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;DatesInPeriod(&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;&amp;lt;dates&amp;gt;, &lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;StartOfMonth/StartOfQuarter/StartOfYear(&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 1.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;DateAdd(&amp;lt;dates&amp;gt;, -1, Month/Quarter/Year)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;),&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;1,&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;Month/Quarter/Year&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;) in case of PreviousMonth/PreviousQuarter/PreviousYear.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;NextDay(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;NextMonth(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;NextQuarter(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;NextYear(&amp;lt;dates&amp;gt;, &amp;lt;year_end_date&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Although not implemented this way, these functions are equivalent to&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;LastDate(DateAdd(&amp;lt;dates&amp;gt;, 1, Day)) in case of NextDay, or&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;DatesInPeriod(&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;&amp;lt;dates&amp;gt;,&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;EndOfMonth/EndOfQuarter/EndOfYear(&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 1.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;DateAdd(&amp;lt;dates&amp;gt;, 1, Month/Quarter/Year)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;),&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;-1,&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 1in;"&gt;&lt;span style="font-family: Calibri;"&gt;Month/Quarter/Year&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt 0.5in;"&gt;&lt;span style="font-family: Calibri;"&gt;) in case NextMonth/NextQuarter/NextYear.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-size: 14pt;"&gt;&lt;span style="font-family: Calibri;"&gt;Composite time intelligence functions&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;The remaining time intelligence functions listed below are always internally rewritten using other time intelligence function.&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;DatesMTD(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;DatesBetween(&amp;lt;dates&amp;gt;, StartOfMonth(LastDate(&amp;lt;dates&amp;gt;)), LastDate(&amp;lt;dates&amp;gt;))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;DatesQTD(&amp;lt;dates&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;DatesBetween(&amp;lt;dates&amp;gt;, StartOfQuarter(LastDate(&amp;lt;dates&amp;gt;)), LastDate(&amp;lt;dates&amp;gt;))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;DatesYTD(&amp;lt;dates&amp;gt;, &amp;lt;year_end_date&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;DatesBetween(&amp;lt;dates&amp;gt;, StartOfYear(LastDate(&amp;lt;dates&amp;gt;), &amp;lt;year_end_date&amp;gt;), LastDate(&amp;lt;dates&amp;gt;))&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;TotalMTD(&amp;lt;expression&amp;gt;, &amp;lt;dates&amp;gt;, &amp;lt;filter&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;Calculate(&amp;lt;expression&amp;gt;, DatesMTD(&amp;lt;dates&amp;gt;), &amp;lt;filter&amp;gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;TotalQTD(&amp;lt;expression&amp;gt;, &amp;lt;dates&amp;gt;, &amp;lt;filter&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;Calculate(&amp;lt;expression&amp;gt;, DatesQTD(&amp;lt;dates&amp;gt;), &amp;lt;filter&amp;gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;TotalYTD(&amp;lt;expression&amp;gt;, &amp;lt;dates&amp;gt;, &amp;lt;filter&amp;gt;, &amp;lt;year_end_date&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;Calculate(&amp;lt;expression&amp;gt;, DatesYTD(&amp;lt;dates&amp;gt;, &amp;lt;year_end_date&amp;gt;), &amp;lt;filter&amp;gt;)&lt;span style="mso-tab-count: 1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;OpeningBalanceMonth(&amp;lt;expression&amp;gt;, &amp;lt;dates&amp;gt;, &amp;lt;filter&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;Calculate(&amp;lt;expression&amp;gt;, PreviousDay(StartOfMonth(&amp;lt;dates&amp;gt;)), filter)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;OpeningBalanceQuarter(&amp;lt;expression&amp;gt;, &amp;lt;dates&amp;gt;, &amp;lt;filter&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;Calculate(&amp;lt;expression&amp;gt;, PreviousDay(StartOfQuarter(&amp;lt;dates&amp;gt;)), filter)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;OpeningBalanceYear(&amp;lt;expression&amp;gt;, &amp;lt;dates&amp;gt;, &amp;lt;filter&amp;gt;, &amp;lt;year_end_date&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;Calculate(&amp;lt;expression&amp;gt;, PreviousDay(StartOfYear(&amp;lt;dates&amp;gt;, &amp;lt;year_end_date&amp;gt;)), filter)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;ClosingBalanceMonth(&amp;lt;expression&amp;gt;, &amp;lt;dates&amp;gt;, &amp;lt;filter&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;Calculate(&amp;lt;expression&amp;gt;, EndOfMonth(&amp;lt;dates&amp;gt;), &amp;lt;filter&amp;gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;ClosingBalanceQuarter(&amp;lt;expression&amp;gt;, &amp;lt;dates&amp;gt;, &amp;lt;filter&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;Calculate(&amp;lt;expression&amp;gt;, EndOfQuarter(&amp;lt;dates&amp;gt;), &amp;lt;filter&amp;gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;b style="mso-bidi-font-weight: normal;"&gt;&lt;span style="font-family: Calibri;"&gt;ClosingBalanceYear(&amp;lt;expression&amp;gt;, &amp;lt;dates&amp;gt;, &amp;lt;filter&amp;gt;, &amp;lt;year_end_date&amp;gt;)&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;span style="font-family: Calibri;"&gt;&lt;span style="mso-tab-count: 1;"&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; &lt;/span&gt;Calculate(&amp;lt;expression&amp;gt;, EndOfYear(&amp;lt;dates&amp;gt;, &amp;lt;year_end_date&amp;gt;), &amp;lt;filter&amp;gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="MsoNormal" style="line-height: normal; margin: 0in 0in 10pt;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8486191632104654344-7471708140894834358?l=mdxdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdxdax.blogspot.com/feeds/7471708140894834358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mdxdax.blogspot.com/2011/01/dax-time-intelligence-functions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/7471708140894834358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/7471708140894834358'/><link rel='alternate' type='text/html' href='http://mdxdax.blogspot.com/2011/01/dax-time-intelligence-functions.html' title='DAX Time Intelligence Functions'/><author><name>Jeffrey Wang</name><uri>http://www.blogger.com/profile/09745744072887789758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8486191632104654344.post-3066383816266765029</id><published>2011-01-06T15:56:00.000-08:00</published><updated>2011-01-07T20:01:34.277-08:00</updated><title type='text'>Execution Plans and Plan Hints for MDX IIF Function and CASE Statement</title><content type='html'>MDX IIF function, and similarly MDX CASE statement,&amp;nbsp;is often a cause of&amp;nbsp;performance issues during execution of MDX formulas.&amp;nbsp; As a developer who worked on this feature, I'll explain the execution plans considered by the MDX formula engine (FE)&amp;nbsp;in this post.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Introduction to some FE concepts&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Before I delve into IIF function, I first need to introduce some basic concepts used by MDX FE.&amp;nbsp;I admit that these concepts can be very complex and are worth several dedicated blog posts.&amp;nbsp;The cursory description here&amp;nbsp;can only give you some general ideas to help you understand execution plans for IIF.&amp;nbsp;You can skip this section directly to the discussion about IIF plans and come back here for references when you need to.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Subspace&lt;/li&gt;&lt;/ul&gt;Every MDX expression is evaluated in a current context which includes a subspace.&amp;nbsp; A subspace is a subset of cells within the cube space.&amp;nbsp;The original subspace is defined by the MDX query, for example, evaluate a measure expression for all product categories and all years.&amp;nbsp;For a given MDX expression, FE will produce a result,&amp;nbsp;like a value for scalar expressions, for every cell in the current subspace.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Rectangular subspace vs. arbitrary-shaped subspace&lt;/li&gt;&lt;/ul&gt;FE represents most subspaces in a very efficient rectangular shape which is a crossjoin of all attributes with non-trivial slices.&amp;nbsp;Many common&amp;nbsp;operations are fast and efficient when performed on rectangular subspaces.&amp;nbsp;For example,&amp;nbsp;search for a cached execution plan; determine whether a cell belongs to a subspace; decide whether an MDX scoped calculation applies to a subspace.&amp;nbsp;But sometimes FE has to create arbitrary-shaped subspaces which you can imagine as rectangular subspaces plus additional constraints such as an enumerated set of tuples.&amp;nbsp;{ food, drink } x { 2009, 2010 } is an example of rectangular subspace.&amp;nbsp;{ (food, 2009), (drink, 2010) } is an example of arbitrary-shaped subspace.&amp;nbsp;In general, Arbitrary-shaped subspaces are bad for performance.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Cell-by-cell mode vs. block mode&lt;/li&gt;&lt;/ul&gt;FE can evaluate a given&amp;nbsp;MDX formula in cell-by-cell mode, in which case FE first builds a context for each cell in the subspace and&amp;nbsp;then calculates the expression in each single-cell context,&amp;nbsp;or in&amp;nbsp;block mode, in which case FE builds a context which contains all cells in the subspace and evaluates the expression in a single scoop.&amp;nbsp;Microsoft introduced MDX block mode execution in SQL Server 2005 and extended it to much more functions in SQL Server 2008.&amp;nbsp;Typically block mode execution is orders of magnitude faster than cell-by-cell execution.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Logical plan&lt;/li&gt;&lt;/ul&gt;An MDX expression is evaluated in multiple stages, at one stage, a logical plan tree is built.&amp;nbsp;If you have any SQL background, don't confuse the logical plan for an MDX expression with the logical plan of relational engine.&amp;nbsp;In particular, MDX FE may need to execute some subtrees in the middle of building a large logical plan tree.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Varying attributes&lt;/li&gt;&lt;/ul&gt;The varying attributes of an MDX expression in a given subspace are those attributes that have more than one member in the subspace and on which the MDX expression depends.&amp;nbsp;Varying attributes of an expression is derived after FE has built a logical plan tree for the expression.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Sparse expression vs. dense expression&lt;/li&gt;&lt;/ul&gt;An MDX scalar expression is called sparse in a subspace if most of the time it produces a single value, typically NULL.&amp;nbsp;For example, physical measures are sparse in typical query subspaces consisting of crossjoin of dimensional attributes.&amp;nbsp;If an MDX expression is not sparse, it is called dense.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Default value&lt;/li&gt;&lt;/ul&gt;The common single value of a sparse MDX scalar expression is called the default value of that expression.&amp;nbsp;The default value of an MDX scalar expression is determined after FE has built a logical plan for the expression.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Execution plans for IIF function&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;span id="goog_457316506"&gt;&lt;/span&gt;&lt;br /&gt;Now&amp;nbsp;we are ready to explore the execution plans of IIF.&amp;nbsp;Implementation of IIF underwent a major overhaul in SQL Server 2008.&amp;nbsp;In SQL Server 2005, there is limited support of block mode for most MDX functions, therefore IIF branches are more often evaluated in cell-by-cell mode.&amp;nbsp;When SQL Server 2005 is able to evaluate IIF in block mode, it evaluates both branches in the original subspace with some special flag to indicate that the subspace may be too large, see eager mode below.&lt;br /&gt;&lt;br /&gt;In this post I focus on the algorithm adopted by SQL Server 2008 and above.&amp;nbsp;As a first step, FE transforms a single&amp;nbsp;IIF&amp;nbsp;function call&amp;nbsp;into nested IIF function calls by&amp;nbsp;eliminating AND operators and OR operators in the predicate expression.&amp;nbsp;Notice that one branch expression is duplicated as a result of this rewrite.&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IIF(a AND b, x, y) =&amp;gt; IIF(a, IIF(b, x, y), y)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IIF(a OR b, x, y) =&amp;gt; IIF(a, x, IIF(b, x, y))&lt;br /&gt;&lt;br /&gt;Next, FE builds a logical plan for the simplified predicate expression.&amp;nbsp;Note that FE may execute some subtrees while building a logical plan tree, this is a big topic which I have to discuss in a seperate blog post.&amp;nbsp;After FE has built a logical plan tree for the predicate expression, FE performs constant folding by checking whether the simplified predicate is constant in the current subspace, and if so, reducing IIF function to one of its branch expressions.&lt;br /&gt;&lt;br /&gt;The next step is to build logical plans for the then branch expression and the else branch expression.&amp;nbsp;FE can evaluate each branch expression in one of two modes: eager mode and strict mode.&amp;nbsp;As mentioned before, the IIF expression is evaluated in a subspace, let's denote it as S0.&amp;nbsp;FE can either evaluate the then branch expression in S0 or FE can build a new subspace, S1, by restricting S0 to those cells that the predicate is true.&amp;nbsp;Similarly, FE can either evaluate the else branch expression in S0 or FE can build another new subspace, S2, by restricting S0 to those cells that the predicate is false.&amp;nbsp;If FE evaluates a branch expression in the original subspace S0, we call it in eager mode.&amp;nbsp;If FE evaluates a branch expression in the restricted subspace S1 or S2, we call it in strict mode.&lt;br /&gt;&lt;br /&gt;Strict mode has the obvious benefit of reducing the number of cells an expression is evaluated, so why doesn't FE choose it all the time?&amp;nbsp;As it turns out, constructing a new subspace by evaluating the predicate will produce an arbitrary-shaped subspace if the varying attributes of the predicate expression contain more than one attribute.&amp;nbsp;In general, arbitrary-shaped subspace can lead to bad performance due to various reasons such as cache misses.&amp;nbsp;Moreover, if a branch expression is simple enough, like when it is a constant value, it doesn't make sense to build a new subspace at all.&lt;br /&gt;&lt;br /&gt;MDX&amp;nbsp;gives user direct control over whether a branch is executed in eager mode or strict mode through branch hints.&amp;nbsp;&amp;nbsp;For example, IIF(p, x HINT EAGER, y HINT STRICT) tells FE to build logical plan in eager mode for the then branch and in strict mode&amp;nbsp;for the else branch.&lt;br /&gt;&lt;br /&gt;When there is no direct hint from user, FE takes several steps to&amp;nbsp;come up with a final logical plan for each branch expression.&amp;nbsp;It first tries to build a logical plan for each branch in eager mode if it is cheap.&amp;nbsp;It is always cheap to build a plan for a constant value expression.&amp;nbsp;When branch expressions are more complex, FE looks at the varying attributes of the predicate logical plan.&amp;nbsp;If the varying attributes contains more than one attribute, hence will produce an arbitrary-shaped subspace which makes an eager plan more appealing, FE first tries to build an eager logical plan tree&amp;nbsp;for a branch expression if it can be cheaply done, in other words, if it can build a plan tree without executing any subtree.&amp;nbsp;In the cheap mode, if at any point in the process of building a logical plan tree for a branch expression, FE finds out that it needs to execute a subtree before it can proceed, FE will abandon the process and roll back all the way to the&amp;nbsp;root of the current tree. I have seen bad performance caused by this trial-and-error process when a deeply nested IIF tree recursively tried to build a cheap plan, aborted the effort, built a real plan, and then repeated this process at the next nesting level. FE may abandon a cheaply built plan when the predicate&amp;nbsp;expression is sparse and&amp;nbsp;a branch with a cheaply built&amp;nbsp;eager plan is on the minority side.&amp;nbsp;For example, if the predicate is mostly true, the else branch is on the minority side.&amp;nbsp;If a branch is on the minority side and&amp;nbsp;if it is dense or if its default value doesn't match the default value of the IIF expression, its cheaply built eager plan will be abandoned.&lt;br /&gt;&lt;br /&gt;At this stage, if FE still&amp;nbsp;doesn't have a logical plan for&amp;nbsp;a branch expression, FE will build a&amp;nbsp;logical plan for that branch in strict mode.&amp;nbsp;It&amp;nbsp;first produces a new subspace for the branch by&amp;nbsp;actually executing the predicate expression, producing a materialized list of tuples of the varying attributes of the predicate that satisfy the condition for that branch, and then applying the list of tuples to the original subspace as a new constraint.&amp;nbsp;FE then generates a logical plan of the branch expression in the new subspace.&lt;br /&gt;&lt;br /&gt;As you can see, MDX FE employes a rule-based approach when building execution plans for IIF function.&amp;nbsp; FE makes decisions based on sparsity and complexity of sub-expressons.&amp;nbsp;Since sparisity of MDX expression is based on heuristics rather than statistics, FE may make the wrong decision which is why we need user hints.&lt;br /&gt;&lt;br /&gt;IIF functions are often deeply nested, although this may not be obvious at first glance.&amp;nbsp;As mentioned earlier in the post, AND and OR operators in IIF predicate are rewritten into nested IIF calls.&amp;nbsp;Searched CASE statement is internally rewritten as nested IIF calls as well.&amp;nbsp;Moreover, MDX script IF statement is also internally mapped to an&amp;nbsp;IIF function call.&amp;nbsp;All these internal tree rewrites make deeply nested IIF trees a common phenomenon in many cube.&lt;br /&gt;&lt;br /&gt;Although MDX FE employes a complex algorithm to build a final plan for the IIF function, we can still learn some basic lessons that may help us understand performance issues associated with the function.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Strict mode helps when a branch expression is very expensive.&amp;nbsp;It can be a lot of extra data has to be read from disk for those extra cells&amp;nbsp;in eager mode.&amp;nbsp;It can also be a very expensive MDX&amp;nbsp;scoped calculation&amp;nbsp;has to be included for one unwanted cell in eager mode.&amp;nbsp;Try plan HINT STRICT if you&amp;nbsp;think AS fetches too much data from disk as a result of evaluating a branch in eager mode.&lt;/li&gt;&lt;li&gt;All the trial-and-errors when building the eager plan can be a source of bad performance when the same IIF function is evaluated many times, typically since the parent function chooses cell-by-cell mode, or when deeply nested IIF calls recursively try eager mode and then fall back to strict mode.&amp;nbsp; Adding plan hints in this case will force FE to make up its mind right away.&lt;/li&gt;&lt;li&gt;Order of predicates in nested IIF calls can be important.&amp;nbsp;A wrong condition at the top level may produce an expensive arbitrary-shaped subspace which makes it&amp;nbsp;expensive to evaluate a child subtree.&amp;nbsp;Or a right condition at the top may save a lot of time by eliminating the need to evaluate a more expensive condition at lower level.&amp;nbsp; Keep in mind that AND and OR operators are rewritten as nested IIF so the order in AND and OR operators is important for the same reason.&lt;/li&gt;&lt;li&gt;Sometimes cell-by-cell mode can be fast&amp;nbsp;especially when a top level function is in cell-by-cell mode.&amp;nbsp;I have seen cases where MDX FE spends a lot of time building plans for a branch expression but never execute the plans as the IIF condition was never met.&amp;nbsp;When the IIF function itself is called many times since its parent is in cell-by-cell mode, all the time FE spent on building unused plans is wasted. Here you may try an undocumented HINT LAZY which applies to all MDX expressions but only takes effect when a server config flag LazyEnabled is set to 1.&amp;nbsp; Using this hint will force FE to delay evaluating the MDX expression until execution time.&amp;nbsp; No logical plan is built by traversing the expression tree.&amp;nbsp; &lt;strong&gt;WARNING&lt;/strong&gt;: You will not get support from Microsoft if you use this hint on your own.&amp;nbsp; You must get approval from Microsoft Customer Service and Support if you want to use this&amp;nbsp;hint in your production system.&lt;/li&gt;&lt;/ul&gt;&lt;strong&gt;Execution plans for CASE statement&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;There are two types of CASE statements: simple case statement and search case statement.&lt;br /&gt;&lt;br /&gt;Search case statement is internally rewritten as nested IIF function calls in the following way:&lt;br /&gt;&lt;br /&gt;CASE&lt;br /&gt;WHEN p1 THEN e1&lt;br /&gt;WHEN p2 THEN e2&lt;br /&gt;...&lt;br /&gt;WHEN pN THEN eN&lt;br /&gt;ELSE eL&lt;br /&gt;END&lt;br /&gt;&lt;br /&gt;=&amp;gt;&lt;br /&gt;&lt;br /&gt;IIF (p1, e1, IIF(p2, e2, ... IIF(pN, eN, eL)...))&lt;br /&gt;&lt;br /&gt;After the rewrite, FE executes all IIF functions according to the algorithm outlined in the previous section.&lt;br /&gt;&lt;br /&gt;SQL Server 2008 SP2 CTP1 introduced a hint for search case statement.&amp;nbsp;The syntax of hint for CASE is:&lt;br /&gt;&lt;br /&gt;CASE HINT &amp;lt;EAGER|STRICT&amp;gt;&lt;br /&gt;WHEN ... THEN ...&lt;br /&gt;...&lt;br /&gt;ELSE ...&lt;br /&gt;END&lt;br /&gt;&lt;br /&gt;Internally, the provided hint is propagated to all branches of all IIF functions generated during the rewrite. Afterwards, FE will use the hint in the same way as hints provided directly to an explicit IIF function.&lt;br /&gt;&lt;br /&gt;The simple case statement has an execution plan similar to that of IIF function.&amp;nbsp;The main difference is that IIF function only&amp;nbsp;has two branches while&amp;nbsp;simple case statement has N branches.&amp;nbsp;As of this writing, users cannot specify eager or strict hints to simple case statements.&lt;br /&gt;&lt;br /&gt;In summary, since MDX IIF function and CASE statement&amp;nbsp;are frequently a source of performance problems, using plan hints may help you solve your problem.&amp;nbsp;Note that plan hints for IIF function are only available in SQL Server 2008 and later and plan hints for&amp;nbsp;search case statement are introduced after SQL Server 2008 SP2 CTP1.&amp;nbsp; I have to admit trying out plan hints is like shooting in the dark due to the lack of end user tools to display MDX execution plan trees.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8486191632104654344-3066383816266765029?l=mdxdax.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://mdxdax.blogspot.com/feeds/3066383816266765029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://mdxdax.blogspot.com/2011/01/mdx-iif-execution-plans-and-plan-hints.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/3066383816266765029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8486191632104654344/posts/default/3066383816266765029'/><link rel='alternate' type='text/html' href='http://mdxdax.blogspot.com/2011/01/mdx-iif-execution-plans-and-plan-hints.html' title='Execution Plans and Plan Hints for MDX IIF Function and CASE Statement'/><author><name>Jeffrey Wang</name><uri>http://www.blogger.com/profile/09745744072887789758</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry></feed>
