<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
	xmlns:media="http://search.yahoo.com/mrss/"
>

<channel>
	<title>Dave's Adventures in Business Intelligence &#187; 2008 GBN &#8211; Dallas</title>
	<atom:link href="http://www.dagira.com/category/conferences/2008-gbn-dallas/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dagira.com</link>
	<description>...you are in a twisty maze of passageways, all different...</description>
	<lastBuildDate>Wed, 28 Jul 2010 13:13:17 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<!-- podcast_generator="podPress/8.8" -->
		<copyright>&#xA9; </copyright>
		<managingEditor>blogmaster@dagira.com ()</managingEditor>
		<webMaster>blogmaster@dagira.com()</webMaster>
		<category></category>
		<ttl>1440</ttl>
		<itunes:keywords></itunes:keywords>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary>...you are in a twisty maze of passageways, all different...</itunes:summary>
		<itunes:author></itunes:author>
		<itunes:category text="Society &amp; Culture"/>
		<itunes:owner>
			<itunes:name></itunes:name>
			<itunes:email>blogmaster@dagira.com</itunes:email>
		</itunes:owner>
		<itunes:block>No</itunes:block>
		<itunes:explicit>no</itunes:explicit>
		<itunes:image href="http://www.dagira.com/wp-content/plugins/podpress/images/powered_by_podpress_large.jpg" />
		<image>
			<url>http://www.dagira.com/wp-content/plugins/podpress/images/powered_by_podpress.jpg</url>
			<title>Dave's Adventures in Business Intelligence</title>
			<link>http://www.dagira.com</link>
			<width>144</width>
			<height>144</height>
		</image>
		<item>
		<title>Time Sliced Measures Part III: Making Measures</title>
		<link>http://www.dagira.com/2009/12/17/time-sliced-measures-part-iii-making-measures/</link>
		<comments>http://www.dagira.com/2009/12/17/time-sliced-measures-part-iii-making-measures/#comments</comments>
		<pubDate>Fri, 18 Dec 2009 03:52:29 +0000</pubDate>
		<dc:creator>Dave Rathbun</dc:creator>
				<category><![CDATA[2008 GBN - Dallas]]></category>
		<category><![CDATA[Universe Contexts]]></category>
		<category><![CDATA[Universe Design]]></category>

		<guid isPermaLink="false">http://www.dagira.com/?p=187</guid>
		<description><![CDATA[In the first post in this series I defined what time-sliced measures are and why they can be useful in a universe. In the second post I described a special calendar table that was designed and built to support the requirements for this solution. I also showed how the join logic worked in conjunction with [...]]]></description>
			<content:encoded><![CDATA[<p>In the <a href="http://www.dagira.com/2009/08/08/time-sliced-measures-part-i-defining-the-problem/">first post in this series</a> I defined what time-sliced measures are and why they can be useful in a universe. In the <a href="http://www.dagira.com/2009/08/28/time-sliced-measures-part-ii-time-slice-calendar-table/">second post</a> I described a special calendar table that was designed and built to support the requirements for this solution. I also showed how the join logic worked in conjunction with the table design. This post completes the implementation. I am finally going to work on the measure objects that a user will see. </p>
<p>In any universe design project I strive for the following goals:</p>
<ul>
<li><strong>Deliver the correct result</strong><br />
In my opinion, this is always the number one goal in any universe design.</li>
<li><strong>User friendly</strong><br />
This is quite important but secondary to correctness</li>
<li><strong>Easy to maintain</strong><br />
Universe maintenance is always allowed to suffer in order to provide the first two attributes on this list, but it is a worthwhile goal to strive for nonetheless</li>
</ul>
<p>In this post I will show how all three of these goals are ultimately met by this implementation. When I am done I will have a completed universe. <em>This post will cover slides 26 through 30 from my 2008 GBN Conference presentation. There is a link to download the file at the end of this post.</em> <span id="more-187"></span></p>
<h3>A Brief Recap</h3>
<p>The overall goals of this project were listed in the prior posts in this series. The most important ones for this post are:</p>
<ul>
<li>Each report is expected to have multiple time-sliced measures</li>
<li>The process of splitting each time-slice time period into its own SQL statement should be completely transparent</li>
</ul>
<p>Current Year and Prior Year are different time slice attributes. Every report is expected to have month-to-date and year-to-date measures that cover both the current and the prior year. That means I expect to see four different measures used in each document. The month and year date ranges are obviously different, as are the current and prior year ranges. In the last post on this topic I described a special time-slice calendar table and set up different aliases for each required time-slice. I set up contexts to keep queries from hitting more than one time-slice at the same time.</p>
<p>That&#8217;s how we got here. Where to next? It&#8217;s time to build some measures.</p>
<h3>Bits and Pieces</h3>
<p>I subscribe to the thought that anything that makes the universe designer&#8217;s job easier while making the user&#8217;s life harder is the wrong approach. However, if I can do something to make my life easier without impacting the user, then whatever I come up with is fair game. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  That&#8217;s how I arrived at the strategy that I am going to outline next.</p>
<p>Normally a &#8220;bit&#8221; is either a one or a zero. Many of the bit objects used in this solution will be just that. However, I am also going to create some special measure bits that make use of the @Select() function. As a general rule I am not in favor of using this function, but in this case I will and I will justify why in a bit. (heh, pun <img src='http://www.dagira.com/wp-includes/images/smilies/icon_razz.gif' alt=':-P' class='wp-smiley' />  )</p>
<p>I am going to focus on creating time-sliced objects for the revenue object. In order to do this, I am going to create a measure bit called &#8220;Revenue&#8221; that contains only the table / columns required to calculate this value. I am <strong>not going to include an aggregation function for this measure</strong> which violates another one of my universe design rules. Again, I will justify why. The other bit objects will be used to select (or mark) which context is used for each time slice.</p>
<h3>Using Measure Bits</h3>
<p>In my time-sliced solution everything is made up of combinations. Imagine a cartesian product between measures and time periods, something like this:</p>
<p><img src="/tips/time_slice_part_iii/cartesian_measures.jpg" /></p>
<p>Each time-slice on the left is combined with each measure on the right. Rather than create six different references to the revenue formula shown here&#8230;</p>
<p><code>INVOICE_LINE.DAYS * INVOICE_LINE.NB_GUESTS * SERVICE.PRICE</code></p>
<p>&#8230;I am going to create just one. Notice that the code shown above does not have an aggregate function? This is by design&#8230; I am going to use the @Select() function to build my visible measure objects. Here&#8217;s the initial part of the object definition for the CY MTD Revenue object.</p>
<p><code>sum(@Select(Measure Bits\Revenue))</code></p>
<p>By leaving the aggregate function out of the source measure I can also create a minimum, maximum, or other aggregate version of the sales revenue. This is because the code referenced by the @Select() doesn&#8217;t have an aggregate&#8230; and why is this important? Because I <strong>can&#8217;t nest aggregate functions</strong>. If my source measure included the sum() function then that&#8217;s all I can do with it. By keeping it generic (no aggregate) I can reuse it with any aggregate function as needed. So that&#8217;s why I am breaking the rule that says every measure must have an aggregate function.</p>
<p>Ultimately the measure bits are going to be hidden from view so they will never be viewable / usable by report writers. They are only used as building blocks in the Designer application.</p>
<h3>Time Slice Bits</h3>
<p>Now I need to build some time-sliced bits. These are really simple. Here&#8217;s what the object definition looks like for the CY MTD bit object.</p>
<p><img src="/tips/time_slice_part_iii/time_bit_definition.jpg" /></p>
<p>The select clause contains the number 1 and that&#8217;s it. Notice what the help text says? In big CAPITAL letters it says &#8220;DON&#8217;T FORGET THE TABLE!!!&#8221; I wonder what that means? <img src='http://www.dagira.com/wp-includes/images/smilies/icon_lol.gif' alt=':lol:' class='wp-smiley' /> </p>
<p>Here&#8217;s what it means. The 1 is just a placeholder to put something in the Select clause. The Where clause is empty. The From clause comes from the table list, and here&#8217;s what that looks like.</p>
<p><img src="/tips/time_slice_part_iii/table_reference.jpg" /></p>
<p>Stick with me just a little bit longer and this will all make sense. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Remember that in the earlier posts I set up aliases for my time-slice calendar table. Each alias became part of its own context. A context is a series of joins that make up a particular path through a universe. What I am working towards is a set of time-sliced objects that a user can drag onto their query panel without having to worry about where they come from or how they&#8217;re put together. Here&#8217;s what my schema looks like as a reminder. All of the aliases are on the right side.</p>
<p><img src="/tips/time_slice_part_iii/schema.jpg" /></p>
<p>This structure gives me a way to automatically split out each time-sliced measure into its own path so that a user can combine CY MTD and PY MTD and any of the other options onto one query and run it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagira.com/2009/12/17/time-sliced-measures-part-iii-making-measures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Time-Sliced Measures Part II: Time Slice Calendar Table</title>
		<link>http://www.dagira.com/2009/08/28/time-sliced-measures-part-ii-time-slice-calendar-table/</link>
		<comments>http://www.dagira.com/2009/08/28/time-sliced-measures-part-ii-time-slice-calendar-table/#comments</comments>
		<pubDate>Fri, 28 Aug 2009 11:51:03 +0000</pubDate>
		<dc:creator>Dave Rathbun</dc:creator>
				<category><![CDATA[2008 GBN - Dallas]]></category>
		<category><![CDATA[Universe Contexts]]></category>
		<category><![CDATA[Universe Design]]></category>

		<guid isPermaLink="false">http://www.dagira.com/?p=166</guid>
		<description><![CDATA[In the first post in this series I defined what time-sliced measures are and why they can be useful in a universe. I also shared the design requirements for a particular project I was on. The requirements included:

Each report is expected to have multiple time-sliced measures
Users must be able to select the type of calendar [...]]]></description>
			<content:encoded><![CDATA[<p>In the <a href="http://www.dagira.com/2009/08/03/time-sliced-measures-part-i-defining-the-problem/">first post in this series</a> I defined what time-sliced measures are and why they can be useful in a universe. I also shared the design requirements for a particular project I was on. The requirements included:</p>
<ul>
<li>Each report is expected to have multiple time-sliced measures</li>
<li>Users must be able to select the type of calendar during the refresh process; calendar types include Monthly and Fiscal</li>
<li>Users can provide any possible date as the &#8220;to date&#8221; for the time slices</li>
<li>The process of splitting each time-slice time period into its own SQL statement should be completely transparent</li>
<li>The resulting SQL should be as efficient as possible</li>
</ul>
<p>In this post I am going to cover the design of a special table that we built in order to support our solution for these requirements. After I talk about the table design I will cover how I use it in the universe, as well as provide a few pros and cons about this solution as I have outlined it so far. Just to prepare you, this post is a bit longer than most that I write, and gets fairly detailed. <em>This post will cover slides 23 through 25 from my 2008 GBN Conference presentation. There is a link to download the file at the end of this post. </em> <span id="more-166"></span></p>
<h3>Time Slice Calendar Table Definition</h3>
<p>Each time slice has a start date and an end date. The actual dates will change based on whether I am looking at a fiscal quarter or a calendar quarter. I need to be able to provide any reference date as my &#8220;to date&#8221; or input date for each time slice. Finally, I want to be able to compare the current year values with the matching prior year values. All of these requirements can be solved with the following table structure:</p>
<table class="blogtable">
<tr>
<th>Column Name</th>
<th>Description</th>
</tr>
<tr class="alt">
<td>ref_cal_dt</td>
<td>Calendar date used as input for prompts</td>
</tr>
<tr>
<td>cal_tmslc_mn_val</td>
<td>Time slice name</td>
</tr>
<tr class="alt">
<td>cal_nm</td>
<td>Calendar name</td>
</tr>
<tr>
<td>curr_yr_tmslc_strt_dt</td>
<td>Current year date range start date</td>
</tr>
<tr class="alt">
<td>curr_yr_tmslc_end_dt</td>
<td>Current year date range end date</td>
</tr>
<tr>
<td>prior_yr_tmslc_strt_dt</td>
<td>Prior year date range start date</td>
</tr>
<tr class="alt">
<td>prior_yr_tmslc_end_dt</td>
<td>Prior year date range end date</td>
</tr>
</table>
<p>The <code>ref_cal_dt</code> is the reference calendar date. Every time I use this table I need to provide that date, either via a prompt or condition of some kind. <em>If you don&#8217;t need the flexibility of redefining the &#8220;to date&#8221; value in your environment this can be removed.</em> The next two columns are codes for the time slice and calendar type. The last four columns contain the starting and ending dates for each time slice; the first two for the current year and the last two are the matching dates for the prior year. I will talk about each of these columns in a bit more detail in the following paragraphs. I am going to save the reference date for last.</p>
<p>The <code>cal_tmslc_mn_val</code> contains values like MTD, QTD, YTD, FM, FQ, and FY. Each of these codes represents a time slice. For example, QTD is Quarter To Date and FQ is Full Quarter. The type of quarter (monthly or fiscal) is determined by the next column.</p>
<p>The <code>cal_nm</code> or Calendar Name column is used to differentiate between the different types of calendars stored in the table. For our implementation we had two calendars, but there is nothing that says I could not create more if needed. I had to create fiscal time slices and calendar type slices to solve my requirement, and the names became <strong>Month Calendar</strong> and <strong>Period Calendar</strong>. I was asked at one point why we stored the full text representation rather than a code. If my memory is correct, we configured this column as a <strong>compressed character</strong> column in Teradata. Since there are only two values, the compression algorithm was very effective.</p>
<p>Here is some sample data from my table. I mentioned earlier that in order to use this table I have to provide an input or &#8220;reference&#8221; date. For the sample data shown below, the reference date was August 15, 2008. The resulting rows show the start date and end date for all of the available time slices for each calendar type (Month or Period). Both the current year (CY) and prior year (PY) date ranges are retrieved on the same row.</p>
<table class="blogtable">
<tr>
<th>Code</th>
<th>Calendar</th>
<th>CY Start Date</th>
<th>CY End Date</th>
<th>PY Start Date</th>
<th>PY End Date</th>
</tr>
<tr class="alt">
<td>MTD</td>
<td>Month Calendar</td>
<td>8/1/2008</td>
<td>8/15/2008</td>
<td>8/1/2007</td>
<td>8/15/2007</td>
</tr>
<tr>
<td>QTD</td>
<td>Month Calendar</td>
<td>7/1/2008</td>
<td>8/15/2008</td>
<td>7/1/2007</td>
<td>8/15/2007</td>
</tr>
<tr class="alt">
<td>YTD</td>
<td>Month Calendar</td>
<td>1/1/2008</td>
<td>8/15/2008</td>
<td>1/1/2007</td>
<td>8/15/2007</td>
</tr>
<tr>
<td>FM</td>
<td>Month Calendar</td>
<td>8/1/2008</td>
<td>8/31/2008</td>
<td>8/1/2007</td>
<td>8/31/2007</td>
</tr>
<tr class="alt">
<td>FQ</td>
<td>Month Calendar</td>
<td>7/1/2008</td>
<td>9/30/2008</td>
<td>7/1/2007</td>
<td>9/30/2007</td>
</tr>
<tr>
<td>FY</td>
<td>Month Calendar</td>
<td>1/1/2008</td>
<td>12/31/2008</td>
<td>1/1/2007</td>
<td>12/31/2007</td>
</tr>
<tr class="alt">
<td>MTD</td>
<td>Period Calendar</td>
<td>8/10/2008</td>
<td>8/15/2008</td>
<td>8/12/2007</td>
<td>8/17/2007</td>
</tr>
<tr>
<td>QTD</td>
<td>Period Calendar</td>
<td>6/15/2008</td>
<td>8/15/2008</td>
<td>6/17/2007</td>
<td>8/17/2007</td>
</tr>
<tr class="alt">
<td>YTD</td>
<td>Period Calendar</td>
<td>12/30/2007</td>
<td>8/15/2008</td>
<td>12/31/2006</td>
<td>8/17/2007</td>
</tr>
<tr>
<td>FM</td>
<td>Period Calendar</td>
<td>8/10/2008</td>
<td>9/6/2008</td>
<td>8/12/2007</td>
<td>9/8/2007</td>
</tr>
<tr class="alt">
<td>FQ</td>
<td>Period Calendar</td>
<td>6/15/2008</td>
<td>9/6/2008</td>
<td>6/17/2007</td>
<td>9/8/2007</td>
</tr>
<tr>
<td>FY</td>
<td>Period Calendar</td>
<td>12/30/2007</td>
<td>12/27/2008</td>
<td>12/31/2006</td>
<td>12/29/2007</td>
</tr>
</table>
<p>What does this tell me? I see that for August 15, 2008, using the <strong>Month Calendar</strong>, the month to date (MTD) range starts on 8/1/2008 <em>(all dates in this blog post are in MM/DD/YYYY format)</em> and ends on 8/15/2008. The full month starts on 8/1/2008 and runs until 8/31/2008. If I switch to the <strong>Period Calendar</strong> instead, I see that the MTD range runs from 8/10/2008 to 8/15/2008, and the full month (fiscal month rather than calendar month at this point) runs from 8/10/2008 to 9/6/2008.</p>
<p>Now, about that reference date&#8230; in our requirements we had to allow the user to redefine the &#8220;to date&#8221; for any time slice. It is fairly standard for the &#8220;to date&#8221; to be the last warehouse refresh date. Since we had to be able to run any report for any &#8220;to date&#8221; our table starts with the reference date. In the sample data posted above, the reference date was always 8/15/2008. I would see another set of rows for 8/16/2008, for 8/17/2008, for 8/18/2008, and so on. Every single possible date value was stored in the time slice table, and the starting / ending date ranges for all time slices and calendar types were computed and stored for each one.</p>
<p>There is one important note about performance that is appropriate at this point. Because we had to be able to roll values up by multiple calendars, we were required to store all of our data at a daily grain in our fact table. Since weeks do not fall on month boundaries, and since fiscal and monthly calendars do not share the same date ranges, the only possible way to solve the issue was to leave things at the daily grain. As you can imagine, this caused some challenges with query performance.</p>
<h3>Join Fact Table to Time Slice Table</h3>
<p>Now that I have thoroughly explained my special calendar table and its contents, how am I going to use it? This table is going to be the &#8220;driver&#8221; for my time-sliced measures, and drivers need roads. <em>(That is, unless you have a <a href="http://www.imdb.com/title/tt0088763/quotes">nuclear powered DeLorean</a>. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  )</em> I&#8217;ve posted before about contexts being paths or routes through a universe, and that&#8217;s what I need here too. But with only one calendar table and one fact table, where will I get different roads? First I need aliases.</p>
<p>I will create an alias of my special calendar table for each time slice definition. That means since I have six time slices (MTD, QTD, YTD, FM, FQ, and FY) and two years (Current Year CY and Prior Year PY) I need to create 12 aliases. After I do that, I create joins from each of these aliases to my fact table. Normally having multiple dimensions per fact is going to be fine, but in this case I want to ensure that every different time slice forces a separate SQL path&#8230; and now I&#8217;m back to where I need to create the contexts.</p>
<p>Here&#8217;s what a slightly simplified version of the universe looks like. I only created the &#8220;To Date&#8221; slices and left the &#8220;full&#8221; versions out for now.</p>
<p><img src="/tips/time_slice_part_ii/schema.jpg" width="600" height="465" border="0" alt="schema picture" title="Island Resorts Marketing with Time Sliced Calendar table" /></p>
<p>Yes, that is a picture of the venerable Island Resorts Marketing universe, but with some aliases of my time-sliced calendar table added. Each of those aliases is joined to the &#8220;fact&#8221; table called <code>SALES</code>. The original <code>CAL_TIMESLICE</code> table is in the universe in the lower left corner. The six aliases are outlined in red on the right. Each alias has a join that looks like this:</p>
<p><code>SALES.INVOICE_DATE between cy_mtd.CURR_YR_TMSLC_STRT_DT and cy_mtd.CURR_YR_TMSLC_END_DT AND cy_mtd.CAL_TMSLC_MN_VAL = 'MTD' AND cy_mtd.CAL_NM = @Prompt('Please select Calendar Type','A','Time Slice Calendar\Calendar Name',mono,free) and cy_mtd.REF_CAL_DT = @Prompt('Please select Calendar Date','D',,mono,free)</code></p>
<p>I will break this down into steps.</p>
<p>The most direct part of the join takes the invoice date and compares it to the time slice start date and end date, using the <code>BETWEEN</code> operator.</p>
<p><code>SALES.INVOICE_DATE between cy_mtd.CURR_YR_TMSLC_STRT_DT and cy_mtd.CURR_YR_TMSLC_END_DT</code></p>
<p>Next, I want to make sure I get exactly one date range, and that is done first by hard-coding the time slice mnemonic value&#8230;</p>
<p><code>cy_mtd.CAL_TMSLC_MN_VAL = 'MTD'</code></p>
<p>&#8230; and then prompting the user to select the calendar type.</p>
<p><code>cy_mtd.CAL_NM = @Prompt('Please select Calendar Type','A','Time Slice Calendar\Calendar Name',mono,free)</code></p>
<p><em>As an aside, I created a join with a prompt for time-slice code as well. This is a nice enhancement that lets the user pick a single measure for their report and on-the-fly swap it from MTD to QTD or YTD or any other defined time-slice. Of course they can only use one at a time, so that is a limitation of that technique.</em></p>
<p>The final part of the join in my case was a date prompt for the reference date. This is the &#8220;to date&#8221; that I talked about earlier in this post. Please note that there is no LOV for the reference date; I rarely provide a list of values for dates since there is not much value added by that overhead.</p>
<p><code>cy_mtd.REF_CAL_DT = @Prompt('Please select Calendar Date','D',,mono,free)</code></p>
<p>The join logic is the same for every alias except for the hard-coded mnemonic code for time slice. </p>
<h3>Checking Join Structure</h3>
<p>In this scenario as I have built it so far, have I introduced any loops? any fan traps? The answer to both of those questions is &#8220;No, I have not.&#8221; However, I have introduced incompatible joins.</p>
<p>For example, suppose that a user picked a MTD and YTD object at the same time. The SQL (abbreviated here) would include this:</p>
<p><code>cy_mtd.CAL_TMSLC_MN_VAL = 'MTD'<br />
AND cy_mtd.CAL_TMSLC_MN_VAL = 'YTD'</code></p>
<p>This is a problem <img src='http://www.dagira.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  but one that I anticipated. At the beginning of this process I said I wanted to create a way to dynamically and transparently generate separate SQL passes for each time slice. I explained the structure and data for my table, and now I have shown how I join that table to my sales fact. The last step is to isolate each one of these aliases into a separate context. Using my shortcut for <a href="http://www.dagira.com/2008/06/19/how-to-copy-a-context/">copying a universe context</a> this step takes only a few minutes to complete for the initial configuration. Each context includes all of the tables from the original Sales context plus exactly one alias of my special calendar table. Here are the joins for the current year MTD alias:</p>
<p><img src="/tips/time_slice_part_ii/context_joins.jpg" width="600" height="218" border="0" alt="Context joins image" title="Joins for the CY MTD Context" /></p>
<p>And then I create a context for each of the others as well; here is a list of the contexts from my universe at this point:</p>
<p><img src="/tips/time_slice_part_ii/context_list.jpg" width="107" height="127" border="0" alt="Context list image" title="List of joins from my time-slice demo universe" /></p>
<h3>Why This Strategy?</h3>
<p>As I have been sharing this design concept at various conferences or with other universe designers I invariably get questions like &#8220;What made you go this route?&#8221; or &#8220;Why not alias the fact table instead?&#8221; and so on. They are fair questions, and I don&#8217;t have time to answer all of them in this post. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  I will try to quickly point out a few advantages to this technique.</p>
<p>If I alias a fact table I can almost certainly guarantee that I will introduce additional loops in my universe structure. There is a limit to the number of loops that can be detected / displayed by Designer, so adding extra loops when I don&#8217;t have to is not in my best interest. Plus, as blog readers will see soon when I start building objects on this structure, there is a big benefit to having all of my measures come from a single fact.</p>
<p>This technique does not add any new chasm or fan traps to the universe.</p>
<p>This technique allows me to support a potentially infinite number of time slices without doing any date calculations on the fly.</p>
<p>This technique allows me to support a potentially infinite number of calendar types. Here I have shown both fiscal and calendar types, but I could easily add more.</p>
<p>On the negative side, there are complexities associated with creating contexts in the universe. I mentioned above that creating the initial contexts is simple. Any future maintenance will be more complex as a result of all of the contexts in the universe. However, I submit that the complexities of the universe are more than paid for by the advantages to the users who will be creating reports. And whether I chose to alias the fact or the calendar table I would still have this issue so it&#8217;s really a moot point.</p>
<h3>Next Steps</h3>
<p>At this point I have accomplished the following:</p>
<ul>
<li>Created and populated my special calendar table</li>
<li>Created aliases for each time slice / year combination (only &#8220;to date&#8221; versions are shown in this post, but I did create the &#8220;full&#8221; aliases and contexts as well in production)</li>
<li>Created joins that link each time-slice calendar alias to my fact</li>
<li>Created contexts to ensure that each time slice will appear in a separate query pass</li>
</ul>
<p>What&#8217;s next? I have to create some objects so my users can make use of all of my hard work so far. That&#8217;s my next post in this series, which will cover slides 26 through 30 of my talk. Stay tuned. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_cool.gif' alt='8-)' class='wp-smiley' /> </p>
<p><strong>Related Links</strong></p>
<ul>
<li>Conference presentation download: <a href="http://www.dagira.com/presentations/2008/2008_GBN_Designer_Essentials.zip">Universe Designer Essentials and Beyond</a></li>
<li>Prior post in this series: <a href="http://www.dagira.com/2009/08/08/time-sliced-measures-part-i-defining-the-problem/">Time-Sliced Measures Part I: Defining the Problem</a></li>
<li>Other supplemental information: <a href="http://www.teradataforum.com/l020829a.htm">Teradata Compression Explained</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.dagira.com/2009/08/28/time-sliced-measures-part-ii-time-slice-calendar-table/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Time-Sliced Measures Part I: Defining the Problem</title>
		<link>http://www.dagira.com/2009/08/08/time-sliced-measures-part-i-defining-the-problem/</link>
		<comments>http://www.dagira.com/2009/08/08/time-sliced-measures-part-i-defining-the-problem/#comments</comments>
		<pubDate>Sat, 08 Aug 2009 15:05:51 +0000</pubDate>
		<dc:creator>Dave Rathbun</dc:creator>
				<category><![CDATA[2008 GBN - Dallas]]></category>
		<category><![CDATA[Universe Design]]></category>

		<guid isPermaLink="false">http://www.dagira.com/?p=124</guid>
		<description><![CDATA[During the 2008 GBN Conference in Dallas I delivered a presentation related to universe design. The last third of the presentation demonstrated a solution for time-sliced measures that I have used on a couple of different projects now. After the presentation I had two different people make suggestions that were proposed as being easier to [...]]]></description>
			<content:encoded><![CDATA[<p>During the 2008 GBN Conference in Dallas I delivered a presentation related to universe design. The last third of the presentation demonstrated a solution for time-sliced measures that I have used on a couple of different projects now. After the presentation I had two different people make suggestions that were proposed as being easier to implement than what I showed.</p>
<p>In each case I was able to tell the person that we had considered and perhaps even tested their suggestion and found it lacking in some way. I didn&#8217;t have time to present all of the different options during the one hour slot that I had at the conference, but I have unlimited time to explain options here on my blog. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  But before I go back and detail things that we tried that did not work out so well, I am going to have a few posts (it&#8217;s too long for just one) about the solution we did implement.</p>
<p><em>This blog post will cover slides 19 through 22 from the 2008 GBN Conference presentation.</em> <span id="more-124"></span></p>
<h3>What is a Time-Sliced Measure?</h3>
<p>Measures are analytical values defined in a universe. Time can be &#8220;sliced&#8221; into intervals like period (or month), quarter, and year. The combination of phrases as &#8220;time-sliced measures&#8221; is generally used to describe special measure objects built in a universe that automatically get associated with a specific time interval. So the measure &#8220;Period to Date Revenue&#8221; would provide a total of revenue for the period to date. In most cases the &#8220;to date&#8221; is the last load date for the database, but it does not have to be so.</p>
<h3>Why are Time-Sliced Measures a Challenge?</h3>
<p>Once time-sliced measures are created, users often want to combine them. A simple query might include Period to Date (PTD) and Year to Date (YTD) for both the Current Year (CY) and the Prior Year (PY) all at the same time. If the time-sliced measures are created with hard-coded date ranges, then each would be incompatible with the rest. A YTD measure has a different date range than a PTD measure. Using both together without some sort of mechanism to split them out would result in the YTD value being impacted by the PTD restriction.</p>
<p>Of course with Web Intelligence users can create multiple data providers. A user could be knowledgable enough to split the various measures into different queries. There are several problems with this approach.</p>
<p>First, it requires the user to know and understand and implement the solution. This requires training and still doesn&#8217;t prevent a user from making a mistake. It&#8217;s also a very repetitive process. Every time a user wants to retrieve more than one time-slice they would be doing the same process over and over. What if there was a way to force Web Intelligence to split the queries into multiple passes for each time-slice instead?</p>
<h3>Contexts Create Multipass SQL Statements</h3>
<p>In the conference presentation I spent a few minutes prior to this topic talking about contexts. Contexts are used to split SQL into multiple passes based on loops, fan, or chasm traps in a universe. At this point I have a problem that requires me to generate multiple SQL statements, and a universe design technique that does just that. It&#8217;s time to put the two together in a solution.</p>
<h3>Business Requirements</h3>
<p>Here are the requirements that I was presented with:</p>
<ul>
<li>Each report is expected to have multiple time-sliced measures</li>
<li>Users must be able to select the type of calendar during the refresh process; calendar types include Monthly and Fiscal</li>
<li>Users can provide any possible date as the &#8220;to date&#8221; for the time slices</li>
<li>The process of splitting each time-slice time period into its own SQL statement should be completely transparent</li>
<li>The resulting SQL should be as efficient as possible</li>
</ul>
<p>The typical time-slices used include CY PTD, CY YTD, PY PTD, and PY YTD. However, the &#8220;P&#8221; in PTD could be Month (MTD) instead of Period based on the result of a prompt. The users on this project needed to be able to see the daily data rolled up my month or period, by calendar or fiscal quarter, and so on. They wanted this to happen automatically so casual adhoc users would be able to use the universe, and of course they wanted the answers in five seconds or less. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  This from a fact table that was expected to grow into the billions of rows. </p>
<p>In the next post for this series I will cover slides 23 through 25 and provide details about the special calendar table we created in our database to support our solution.</p>
<p><strong>Related Links</strong></p>
<ul>
<li><a href="http://www.dagira.com/presentations/2008/2008_GBN_Designer_Essentials.zip">Universe Designer Essentials and Beyond</a> conference presentation</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.dagira.com/2009/08/08/time-sliced-measures-part-i-defining-the-problem/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Context Versus Alias Overview</title>
		<link>http://www.dagira.com/2009/07/22/context-versus-alias-overview/</link>
		<comments>http://www.dagira.com/2009/07/22/context-versus-alias-overview/#comments</comments>
		<pubDate>Wed, 22 Jul 2009 14:24:36 +0000</pubDate>
		<dc:creator>Dave Rathbun</dc:creator>
				<category><![CDATA[2008 GBN - Dallas]]></category>
		<category><![CDATA[Universe Contexts]]></category>
		<category><![CDATA[Universe Design]]></category>

		<guid isPermaLink="false">http://www.dagira.com/?p=163</guid>
		<description><![CDATA[In an attempt to complete the blog posts related to my GBN Conference presentation from 2008 before the upcoming conference in 2009 kicks off I bring you Context Versus Alias: The Smackdown Cage Match.   People often post on BOB as if contexts and aliases are competing for the same job, and that is [...]]]></description>
			<content:encoded><![CDATA[<p>In an attempt to complete the blog posts related to my GBN Conference presentation from 2008 before the upcoming conference in 2009 kicks off I bring you Context Versus Alias: The Smackdown Cage Match. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_lol.gif' alt=':lol:' class='wp-smiley' />  People often post on BOB as if contexts and aliases are competing for the same job, and that is certainly not true. Each technique has an appropriate use, and I will cover them (although not in much depth) in this post. I won&#8217;t be showing the process for creating contexts or aliases in this post as it would end up being too long.</p>
<p><em>This post is related to slides 13 through 17 from my <a href="http://www.dagira.com/presentations/2008/2008_GBN_Designer_Essentials.zip">2008 conference presentation</a>.</em> <span id="more-163"></span></p>
<h3>What is an Alias?</h3>
<p>The alias technique has been around far longer than Business Objects has. Whenever a SQL script needs to access the same table more than once an alias is used. One of the easiest examples is an employee table that contains a key to the employee&#8217;s manager. In order to return a list of employees and who they work for I might write SQL code something like this:</p>
<p><code>SELECT emp.name<br />
, mgr.name<br />
FROM employees emp<br />
, employees mgr<br />
WHERE emp.mgr_id = mgr.emp_id</code></p>
<p>There is only one table in the code: the <code>employees</code> table. However, in order to get the employee name <strong>and</strong> the manager name, I need to join the table back to itself. In order to accomplish that, I have to give each side of the relationship a unique name. That is the SQL alias for each table, and the same technique is used in building universes.</p>
<p>Aliases are more typical in a universe environment with lookup tables. For example, in the screen shot shown below (taken from my presentation) the <code>COUNTRY</code> table has two unique purposes. In one case it is used to show where a Resort is located. In the other case it contains the Region for each customer. An alias is indicated by the fact that the <code>COUNTRY</code> table is always on the &#8220;one&#8221; side of a one-to-many join. This issue (and solution) can be found in the Island Resorts universe.</p>
<p><img src="/tips/alias_vs_context/country_joins.jpg" width="494" height="105" border="0" alt="country join example" title="Country joins showing two purposes for the table" /></p>
<p>To summarize so far: an alias is used when the same table is used more than once, and is typically indicated by that table always being on the &#8220;one&#8221; side of a one-to-many join.</p>
<h3>What is a Context?</h3>
<p>A context, on the other hand, is a concept that probably originated within a universe. If a SQL developer decides that he or she needs two scripts to get the job done, then that&#8217;s what they write. But a universe is supposed to be able to generate SQL for a non-developer. So how can it have the intelligence to know when to split something into multiple SQL passes? That is the role of a context.</p>
<p>Here is another screen shot borrowed from my presentation.</p>
<p><img src="/tips/alias_vs_context/context_paths.jpg" width="481" height="268" border="0" alt="context path example" title="Reservations and Sales Contexts example" /></p>
<p>In the diagram shown above, the two end points are <code>CUSTOMER</code> and <code>SERVICE</code>. There are two ways to figure out which service a customer is related to. The first relationship goes through the reservations tables and is used to show which services a customer has requested. The second relationship goes through the sales tables and is used to bill the customer for services used. These relationships are equally important.</p>
<p>A context is indicated in this case because there is a loop. <em>(Please note, however, that contexts also solve fan and chasm traps which do not involve loops.)</em> A loop in a universe is found when a sequence of joins can be selected that start and end at the same table. In this case, I could map from the <code>CUSTOMER</code> table through the <code>INVOICE_LINE</code> table, the <code>SERVICE</code> table, back through the reservations tables and end up back where I started. That&#8217;s a loop. If the loop is not resolved in some way, Desktop Intelligence and Web Intelligence will issue an &#8220;incompatible combination of objects&#8221; message rather than run the invalid SQL.</p>
<p>An alias was indicated by tables on the &#8220;one&#8221; side of every join. Contexts are indicated by tables appearing only on the &#8220;many&#8221; side of a one-to-many join. In this loop, those are the <code>RESERVATION_LINE</code> and <code>INVOICE_LINE</code> tables. Those tables will ultimately drive my context creation process.</p>
<p>To summarize contexts: they are used to resolve loops (and other SQL traps) and are indicated by tables always appearing on the &#8220;many&#8221; side of a one-to-many join.</p>
<h3>Context Versus Alias</h3>
<p>I have shown examples of where each technique would be appropriate. Is it possible to use an alias to solve a context issue, or a context to solve an alias challenge? To be honest, yes. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  But you would end up creating more problems than you solve. Here&#8217;s a summary of the two features:</p>
<ul>
<li>Alias Features
<ul>
<li>Aliases are simple to create</li>
<li>Objects for each alias can be created, for example Resort Country and Customer Country from my example given above</li>
<li>Once created no further maintenance is required</li>
<li>Aliases eliminate (break) loops</li>
</ul>
</li>
<li>Context Features
<ul>
<li>Contexts are more complex to create</li>
<li>Every join must exist in at least one context; if not, it becomes an <em>isolated join</em></li>
<li>Loops are not eliminated; two (or more) paths are identified and used but the loop remains</li>
<li>Contexts can also resolve <a href="http://www.dagira.com/category/design/fan-chasm-trap/">fan or chasm traps</a></li>
</ul>
</li>
</ul>
<p>I have seen more than one post on <a href="http://busobj.forumtopics.com">BOB</a> where people say things like, &#8220;&#8230; my client doesn&#8217;t allow contexts&#8230;&#8221; or &#8220;&#8230; won&#8217;t use contexts because they are too complicated&#8230;&#8221; and I cringe. You would not use a hammer to put in a screw because a screw-driver is &#8220;too complex&#8221; so why would you use the wrong tool to resolve an issue in a universe? It doesn&#8217;t make sense.</p>
<h3>Conclusion</h3>
<p>Aliases and contexts are not substitutes for each other: each has a unique purpose and a place in universe design. I tried to show that in my brief overview slides in my presentation, and hopefully have added some value by including more detail in this post. I have other posts on contexts and aliases and other universe design issues published, and a few more in draft form that I hope to finish as time allows. The complete presentation can be downloaded from my presentations page, linked below.</p>
<p><strong>Related Links</strong></p>
<ul>
<li><a href="http://www.dagira.com/conference-presentations/">Conference presentations page</a></li>
<li><a href="http://www.dagira.com/presentations/2008/2008_GBN_Designer_Essentials.zip">Universe Designer Essentials and Beyond</a> conference presentation</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.dagira.com/2009/07/22/context-versus-alias-overview/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Webinar is Done, Whew!</title>
		<link>http://www.dagira.com/2008/11/18/webinar-is-done-whew/</link>
		<comments>http://www.dagira.com/2008/11/18/webinar-is-done-whew/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 20:44:21 +0000</pubDate>
		<dc:creator>Dave Rathbun</dc:creator>
				<category><![CDATA[2008 GBN - Dallas]]></category>
		<category><![CDATA[GBN]]></category>

		<guid isPermaLink="false">http://www.dagira.com/?p=133</guid>
		<description><![CDATA[Earlier today I delivered my GBN Conference presentation to an audience over the web. It was&#8230; interesting.   I have done web presentations before but never to an audience of this size. I didn&#8217;t have time to count, but it seemed like there were well over 100 attendees that stayed through to the very [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier today I delivered my GBN Conference presentation to an audience over the web. It was&#8230; interesting. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  I have done web presentations before but never to an audience of this size. I didn&#8217;t have time to count, but it seemed like there were well over 100 attendees that stayed through to the very end. I hope they (or you, if you were online) found the time to be worthwhile.</p>
<p>It was certainly different for me. Presenting to a live audience is not stressful to me at all anymore. I have enough experience that it just doesn&#8217;t bother me. Whether I am delivering a training class to an audience of ten, or a conference presentation to an audience of hundreds, it doesn&#8217;t make me nervous at all. But today on the call was a different story. <span id="more-133"></span>I was quite nervous! I had all sorts of worries. What if my Internet connection goes down? What if my dog barks, or my doorbell rings? (I was doing the presentation from home to avoid the background noise from being in an office.) None of those things happened, which is good. </p>
<p>What I didn&#8217;t realize until going through the presentation was how much I &#8220;feed&#8221; off of and react to the audience during a live presentation. When I am delivering live content I get a feel for whether people are interested in what I have to say. As long as their eyes are open and facing forward, and heads nod in appropriate places, I figure things are going okay.</p>
<p>On a webinar, that wasn&#8217;t possible.</p>
<p>I logged in to the webinar website as the presenter from my laptop. I also logged in as an attendee from my desktop. By doing that, I was able to monitor exactly what everyone else was seeing. I think that helped because it was easy to make sure I didn&#8217;t get ahead of the screen refresh. I also tried to keep an eye on the chat room and watch for questions. When I could, I tried to incorporate answers from chat questions into my talk. I think that process went okay, but I know that I would do a better job next time.</p>
<p>In any case, if you&#8217;ve <a href="http://www.gogbn.org/irj/portal/anonymous/gbnselfregister">joined the GBN</a> you&#8217;ll soon be able to review the webinar online and judge for yourself. I don&#8217;t have an estimated time for publication, but as soon as I find out that the session is available I will be sure to post it here.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagira.com/2008/11/18/webinar-is-done-whew/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Designer Essentials Webcast Scheduled November 18</title>
		<link>http://www.dagira.com/2008/11/11/designer-essentials-webcast-scheduled-november-18/</link>
		<comments>http://www.dagira.com/2008/11/11/designer-essentials-webcast-scheduled-november-18/#comments</comments>
		<pubDate>Tue, 11 Nov 2008 18:49:57 +0000</pubDate>
		<dc:creator>Dave Rathbun</dc:creator>
				<category><![CDATA[2008 GBN - Dallas]]></category>
		<category><![CDATA[GBN]]></category>

		<guid isPermaLink="false">http://www.dagira.com/?p=130</guid>
		<description><![CDATA[The presentation that I did for the 2008 GBN conference earlier this year has been scheduled for a webcast that will be hosted on the GBN web site. Registration is required, but it&#8217;s fairly simple. If you go to the GBN Home Page there is a link for Webcast Series on the right side of [...]]]></description>
			<content:encoded><![CDATA[<p>The presentation that I did for the 2008 GBN conference earlier this year has been scheduled for a webcast that will be hosted on the GBN web site. Registration is required, but it&#8217;s fairly simple. If you go to the <a href="http://www.gogbn.org/">GBN Home Page</a> there is a link for Webcast Series on the right side of the screen. Clicking that link will take you to the schedule, and a link to sign up for the various presentations, including this one.</p>
<p>There are other speakers from the GBN conference that will be delivering their presentations in this format as well. I just get to go first and iron out all of the bugs in the process. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagira.com/2008/11/11/designer-essentials-webcast-scheduled-november-18/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Designer XI 3 New Feature: Database Delegated Measures</title>
		<link>http://www.dagira.com/2008/11/10/designer-xi-3-new-feature-database-delegated-measures/</link>
		<comments>http://www.dagira.com/2008/11/10/designer-xi-3-new-feature-database-delegated-measures/#comments</comments>
		<pubDate>Mon, 10 Nov 2008 12:34:54 +0000</pubDate>
		<dc:creator>Dave Rathbun</dc:creator>
				<category><![CDATA[2008 GBN - Dallas]]></category>
		<category><![CDATA[Universe Design]]></category>

		<guid isPermaLink="false">http://www.dagira.com/?p=128</guid>
		<description><![CDATA[A Brief Overview of Measure Objects
A universe has three basic types of result objects: dimensions, details, and measures. Measure objects are analytical values like dollars or quantities. Measure objects have two extra settings that dimensions and details do not have: a SQL aggregate function and a report Projection function. The SQL aggregate function is not [...]]]></description>
			<content:encoded><![CDATA[<h3>A Brief Overview of Measure Objects</h3>
<p>A universe has three basic types of result objects: dimensions, details, and measures. Measure objects are analytical values like dollars or quantities. Measure objects have two extra settings that dimensions and details do not have: a SQL aggregate function and a report Projection function. The SQL aggregate function is not enforced by the application, but it should always be present. (That&#8217;s a subject for another blog post. Or two.)</p>
<p>The SQL aggregate function is performed by the database server, and the projection function is used by the report engine. This is what makes measures &#8220;roll up&#8221; when you slice and dice or drill on a report. The problem is, certain calculations cannot be done by the database because there is no valid projection function. Designer 3.x gives me a way to address that by introducing a new projection function setting of <strong>Database delegated</strong>. This post will explain why that&#8217;s important and how it works.<br />
<span id="more-128"></span><br />
<h3>How Projection Works</h3>
<p>The projection function is designed to complement the SQL aggregation operation. For example the Revenue object from Island Resorts has the following SQL formula:</p>
<pre>sum(INVOICE_LINE.DAYS * INVOICE_LINE.NB_GUESTS * SERVICE.PRICE)</pre>
<p>The object also has a Sum projection function. If I run a query that returns the Resort and the Year and the Revenue the output looks like this:</p>
<p><img src="/tips/delegated_measures/raw_data.jpg" width="325" height="313" alt="Raw Data" title="Raw data with Resort, Year, and Revenue" border="0" /></p>
<p>Using a simple drag-and-drop technique I can remove the Year from the output block and the projection function causes the data to roll up to this result:</p>
<p><img src="/tips/delegated_measures/projected_data.jpg" width="217" height="97" alt="Projected Data" title="Projected data with Resort and Revenue" border="0" /></p>
<p>This is all controlled via the projection function which is a part of the object properties screen as shown here:</p>
<p><img src="/tips/delegated_measures/projection_sum.jpg" width="442" height="167" alt="Projection Function" title="Projection function definition" border="0" /></p>
<h3>When Projection Fails</h3>
<p>This all works very well until a special function like Average is considered. Averages cannot easily be projected because the source data could be very skewed. A sum operation can be applied recursively. What this means is that 1 + 5 generates the same result as 1 + (2 + 3). An average is not recursive. An average of 1 and 2.5 is not the same as an average of 1, 2, and 3. For the record, and average of 1 and 2.5 is 1.75, and an average of 1, 2, and 3 is 2. Even with a very small set of data the results of an average projection can be very wrong.</p>
<p>The basic problem here is that averages have to work with the source data. I cannot apply an average to an average and expect to get the correct result. It is for this reason that report developers have had to create average and percentage calculations on their reports rather than reusing an object from a universe. In order to deliver the correct result I have to work with the source data.</p>
<h3>Averages Do Not Average Well</h3>
<p>As I said in the prior paragraph, the only way to generate the correct result for an average is to recalculate it from the source data. In order to demonstrate this I have created an Average Revenue object in my universe. For this screen shot I have used the average object in two different queries. The first shows Average Revenue by Resort and Year, and the second shows Average Revenue by Resort only.</p>
<p><img src="/tips/delegated_measures/average_data.jpg" width="565" height="313" alt="Average Data" title="Average Data in Two Blocks" border="0" /></p>
<p>The object is created with the following SQL:</p>
<pre>avg(INVOICE_LINE.DAYS * INVOICE_LINE.NB_GUESTS * SERVICE.PRICE)</pre>
<p>&#8230; and the projection function is set to Average. As I did before I can apply a simple drag-and-drop operation to remove the Year object from the first block, allowing the report engine to project the Average Revenue using the selected projection function of Average. Are the results correct?</p>
<p><img src="/tips/delegated_measures/projected_average.jpg" width="457" height="97" alt="Projected Average Data" title="Projected Average Data in Two Blocks" border="0" /></p>
<p>The results are wrong because the projection in the first block is taking three years of data, summing them up, and then dividing the total by three to get the new average value. The true result based on a database calculation is shown in the right block. The second block was not affected by the Year values since the query did not include that object in the result set.</p>
<h3>Delegated Measures</h3>
<p>This is where the delegation process comes in. As a universe designer I can now create an object that will project correctly (yay) at the expense of having to run a database query (boo). Instead of projecting my average calculation using the Average function, I will use the Database Delegated option instead. Here&#8217;s how that looks:</p>
<p><img src="/tips/delegated_measures/delegated.jpg" width="240" height="103" alt="Delegated Projection" title="Delegated Projection Function" border="0" /></p>
<p>When I run the same query with my new measure definition here is what the initial output looks like:</p>
<p><img src="/tips/delegated_measures/average_data.jpg" width="565" height="313" alt="Average Data" title="Average Data in Two Blocks" border="0" /></p>
<p>The difference becomes apparent when I drag-and-drop the Year object away from my block:</p>
<p><img src="/tips/delegated_measures/to_refresh.jpg" width="457" height="97" alt="Average Data" title="Projected Average Data with Delegation Active" border="0" /></p>
<p>The note #TOREFRESH is telling me that before I can see the numbers for that column I have to refresh my document. I think that it&#8217;s nice that it doesn&#8217;t refresh right away, as it gives me the opportunity to make more adjustments. Perhaps on a more complex report I want to remove (or add) more than one object from the block. In any case, when I click the refresh button the results are displayed.</p>
<p><img src="/tips/delegated_measures/to_refresh_after.jpg" width="457" height="97" alt="Average Data" title="Projected Average Data After Refresh" border="0" /></p>
<p>Note that the two blocks are 100% the same now. The option to delegate the average calculation to the database has given me the power to create an entirely new type of object that I could not have done before.</p>
<h3>Conclusion</h3>
<p>This is another nice new feature for Designer. It will provide me with better control over how my measure objects are handled. In this case, the solution is not without a cost&#8230; I may have to refresh the report in order to force the data to be updated. If the query takes a long time to run, there is a cost involved. It may ultimately still be easier to do this type of calculation on the report.</p>
<p>Here is another challenge that is not solved by this technique: I can&#8217;t do calculations that cross contexts in the universe. Suppose that I have one context for current year measures, and a second context for prior year measures. If I want to compare current to prior year values, that has to be done on the report. Delegating that calculation to the database is not possible because the values come from two different contexts.</p>
<p>But it&#8217;s nice to have options.</p>
<p><em>This feature was one of several mentioned in my Designer Essentials presentation delivered at the 2008 GBN conference. This particular feature was on page 10.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagira.com/2008/11/10/designer-xi-3-new-feature-database-delegated-measures/feed/</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
		<item>
		<title>Designer XI 3 New Feature: Class Restrictions</title>
		<link>http://www.dagira.com/2008/11/05/designer-xi-3-new-feature-class-restrictions/</link>
		<comments>http://www.dagira.com/2008/11/05/designer-xi-3-new-feature-class-restrictions/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 12:28:53 +0000</pubDate>
		<dc:creator>Dave Rathbun</dc:creator>
				<category><![CDATA[2008 GBN - Dallas]]></category>
		<category><![CDATA[Universe Design]]></category>

		<guid isPermaLink="false">http://www.dagira.com/?p=125</guid>
		<description><![CDATA[Designer has provided the option to create &#8220;stub joins&#8221; in a universe for quite a few years. A stub join is a permanent where clause on a table that appears as a small stub rather than a full join connecting two tables. This feature has often been used to apply security to a table via [...]]]></description>
			<content:encoded><![CDATA[<p>Designer has provided the option to create &#8220;stub joins&#8221; in a universe for quite a few years. A stub join is a permanent where clause on a table that appears as a small stub rather than a full join connecting two tables. This feature has often been used to apply security to a table via a reference to the @Variable(&#8217;BOUSER&#8217;) value.</p>
<p>However this strategy had one major flaw in that if the table was not referenced in the query then the security would not be applied. I now have a much more flexible (and powerful) option in Designer 3: Class Restrictions.</p>
<p><span id="more-125"></span><br />
<h3>Stub Join Review</h3>
<p>Here is what a stub join looks like in the structure window.</p>
<p><img src="/tips/class_filters/stub_join.jpg" alt="stub join" title="Stub join in a universe" border="0" width="113" height="73" /></p>
<p>The extra stub hanging off of the table includes the following syntax:</p>
<p><code>RESORT_COUNTRY.COUNTRY_ID = 1</code></p>
<p>The intent of this simple restriction is to apply a restriction so that the only country allowed to be displayed in this universe is the US, or Country ID of 1. Does it work? Sort of.</p>
<p>If I create this query:</p>
<p><img src="/tips/class_filters/query_objects.jpg" alt="Query Objects" title="Objects selected for my query" border="0" width="253" height="67" /></p>
<p>&#8230; here is the SQL code generated:</p>
<p><code>SELECT<br />
  RESORT.resort,<br />
  SERVICE_LINE.service_line,<br />
  SERVICE.service<br />
FROM<br />
  SERVICE,<br />
  SERVICE_LINE,<br />
  RESORT<br />
WHERE<br />
  ( RESORT.RESORT_ID=SERVICE_LINE.RESORT_ID  )<br />
  AND  ( SERVICE_LINE.SL_ID=SERVICE.SL_ID  )</code></p>
<p>If I include the country object in the query, then this is the SQL code generated:</p>
<p><code>SELECT<br />
  RESORT_COUNTRY.country,<br />
  RESORT.resort,<br />
  SERVICE_LINE.service_line,<br />
  SERVICE.service<br />
FROM<br />
  SERVICE,<br />
  SERVICE_LINE,<br />
  COUNTRY  RESORT_COUNTRY,<br />
  RESORT<br />
WHERE<br />
  ( RESORT_COUNTRY.COUNTRY_ID=RESORT.COUNTRY_ID  )<br />
  AND  ( RESORT.RESORT_ID=SERVICE_LINE.RESORT_ID  )<br />
  AND  ( SERVICE_LINE.SL_ID=SERVICE.SL_ID  )<br />
  <strong>AND  ( RESORT_COUNTRY.COUNTRY_ID = 1  )</strong></code></p>
<p>The important difference is that the first query does <strong>not include the intended restriction</strong>. Why not? Because the stub join is only included when the affected table is included in the query. This is a fairly substantial drawback to this technique.</p>
<h3>Class Restrictions</h3>
<p>Here is where this new feature shines. I can create a class restriction that is applied to every object from the class. The philosophy is similar; a stub join is applied to every element from a table; the class restriction extends the concept to a universe class. Is this powerful?</p>
<p>If I create the same query as above:</p>
<p><img src="/tips/class_filters/query_objects.jpg" alt="Query Objects" title="Objects selected for my query" border="0" width="253" height="67" /></p>
<p>&#8230; here is the SQL generated:</p>
<p><code>SELECT<br />
  RESORT.resort,<br />
  SERVICE_LINE.service_line,<br />
  SERVICE.service<br />
FROM<br />
  SERVICE,<br />
  SERVICE_LINE,<br />
  COUNTRY  RESORT_COUNTRY,<br />
  RESORT<br />
WHERE<br />
  ( RESORT_COUNTRY.COUNTRY_ID=RESORT.COUNTRY_ID  )<br />
  AND  ( RESORT.RESORT_ID=SERVICE_LINE.RESORT_ID  )<br />
  AND  ( SERVICE_LINE.SL_ID=SERVICE.SL_ID  )<br />
  AND<br />
  <strong>( RESORT_COUNTRY.COUNTRY_ID = 1  )</strong></code></p>
<p>Look carefully, and you will see that the RESORT_COUNTRY table is not included in the SELECT clause at all, yet the restriction is still applied to the query. How was this done?</p>
<h3>Building a Class Restriction</h3>
<p>I start the process using the same technique that I would use to build a standard predefined condition in the universe. I create the new condition with the appropriate logic, as shown in the screen here. The new features are configured using the options on the lower corner of the dialog box.</p>
<p><img src="/tips/class_filters/class_filter.jpg" alt="class filter image" title="Creating a Class Filter on a Universe in Designer 3.x" border="0" width="550" height="404" /></p>
<p>All I have to do is check the &#8220;manditory&#8221; box and select <strong>Apply on Class</strong> and the condition is applied to every object from that class. If I create additional objects and insert them into that class, these new objects will automatically inherit the same condition restriction without additional work from me.</p>
<p>And it gets better. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Building a Universe Filter</h3>
<p>Here is a closer view of the options on the dialog box:</p>
<p><img src="/tips/class_filters/filter_where.jpg" alt="zoomed filter image" title="Closer view of the class / universe restrictions in Designer 3.0" border="0" width="375" height="140" /></p>
<p>There are two choices: <strong>Apply on Universe</strong> and <strong>Apply on Class</strong>. Hmm.. I wonder what the first choice does? <img src='http://www.dagira.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>I selected the Apply on Universe option and created a query that referenced several different tables in order to derive the sales revenue. Here is the SQL that was generated:</p>
<p><code>SELECT<br />
  sum(INVOICE_LINE.DAYS * INVOICE_LINE.NB_GUESTS * SERVICE.PRICE)<br />
FROM<br />
  INVOICE_LINE,<br />
  SERVICE,<br />
  SERVICE_LINE,<br />
  COUNTRY  RESORT_COUNTRY,<br />
  RESORT<br />
WHERE<br />
  ( RESORT_COUNTRY.COUNTRY_ID=RESORT.COUNTRY_ID  )<br />
  AND  ( RESORT.RESORT_ID=SERVICE_LINE.RESORT_ID  )<br />
  AND  ( SERVICE_LINE.SL_ID=SERVICE.SL_ID  )<br />
  AND  ( SERVICE.SERVICE_ID=INVOICE_LINE.SERVICE_ID  )<br />
  AND<br />
  <strong>( RESORT_COUNTRY.COUNTRY_ID = 1  )</strong></code></p>
<p>This is powerful stuff. I could create a hidden class in my universe, create any number of predefined conditions as universe filters, and leverage the @variable(&#8217;BOUSER&#8217;) restriction to apply security to the entire universe. No matter which objects a user selects for their query, my security would get applied 100% of the time. I like it. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_cool.gif' alt='8-)' class='wp-smiley' /> </p>
<h3>Conclusion</h3>
<p>Stub joins were often used to apply security via a reference to the BOUSER variable. The problem with this solution is that the security was only applied to that table. If the query did not reference that table, the security didn&#8217;t get applied. The work required by the designer at this point was substantial&#8230; he or she would have to work through the entire universe and add that table to every object reference.</p>
<p>As a universe designer I now have the option to create a special condition at a class level. I can even create a condition that will be applied accross the entire universe. This is good stuff, and a feature that I am sure will be well received by universe designers everywhere.</p>
<p><em>This feature was one of several mentioned in my Designer Essentials presentation delivered at the 2008 GBN conference. This particular feature was on page 11.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagira.com/2008/11/05/designer-xi-3-new-feature-class-restrictions/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Designer XI 3 New Feature: Extended Prompt Syntax</title>
		<link>http://www.dagira.com/2008/11/01/designer-xi-3-new-feature-extended-prompt-syntax/</link>
		<comments>http://www.dagira.com/2008/11/01/designer-xi-3-new-feature-extended-prompt-syntax/#comments</comments>
		<pubDate>Sat, 01 Nov 2008 12:44:36 +0000</pubDate>
		<dc:creator>Dave Rathbun</dc:creator>
				<category><![CDATA[2008 GBN - Dallas]]></category>
		<category><![CDATA[Prompts]]></category>
		<category><![CDATA[Universe Design]]></category>

		<guid isPermaLink="false">http://www.dagira.com/?p=126</guid>
		<description><![CDATA[The @Prompt() function has been around for a very long time. There have been subtle changes made to it over the years to support some of the new Web Intelligence extended options but they were not always documented. I don&#8217;t know about you, but I find using undocumented features a bit daunting.  

Documentation is [...]]]></description>
			<content:encoded><![CDATA[<p>The @Prompt() function has been around for a very long time. There have been subtle changes made to it over the years to support some of the new Web Intelligence extended options but they were not always documented. I don&#8217;t know about you, but I find using undocumented features a bit daunting. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><span id="more-126"></span><br />
<h3>Documentation is Good</h3>
<p>Designer 3.0 is the first time that I have been able to find the extended prompt syntax documented. It even mentions the <code>primary_key</code> attribute which was apparently present (and usable) in XI R2. This feature allows me to create prompts in the Universe Designer that will still <a href="http://www.dagira.com/2007/10/26/index-awareness-part-i-the-basics/">leverage Index Awareness</a>, assuming I have set that up.</p>
<p>Here is the prompt syntax shown in the XI 3 Designer manual:</p>
<blockquote><p>@Prompt(&#8217;message&#8217;,'type&#8217;,[lov],mono/multi,free/constrained/primary_key,per<br />
sistent/not_persistent, [{'default value':'default key'[,'default value':'default<br />
key',...]})</p></blockquote>
<p>I&#8217;ve <a href="http://www.dagira.com/2008/07/15/how-can-i-make-today-my-default-prompt-value/">covered the prompt syntax before</a> so I won&#8217;t review everything. But the new features are interesting. The new feature <code>primary_key</code> was used in my &#8220;Ninja&#8221; presentation from last year with a disclaimer about it being an &#8220;undocumented feature&#8221; and the note of being a bit risky to use as a result. Now it is not only documented but there is a modifier for the default value option as well.</p>
<h3>Using Index Aware Objects With Prompts</h3>
<p>Recall that index awareness is designed to create more efficient SQL. Instead of </p>
<p><code>RESORT.RESORT = 'Bahamas Beach'</code> </p>
<p>I would see </p>
<p><code>RESORT.RESORT_ID = 2</code></p>
<p>With the new prompt parameter I can specify the default value in a <code>value:key</code> pair, like this:</p>
<p><code>RESORT.RESORT_ID = @Prompt('Please select Resort', 'A', 'Resort\Resort', mono, primary_key, not_persistent,{'Bahamas Beach':'2'})</code></p>
<p>The option <code>mono</code> of course means I will only select one value. That is not new. The option <code>primary_key</code> tells the SQL generator that this object is index aware, and that I want the key to be used rather than the value. The option <code>not_persistent</code> is used to tell the SQL generator that I don&#8217;t want to retain the last user selected value. And finally, the string <code>'Bahamas Beach':'2'</code> is used to show that the default value shown to the user is Bahamas Beach but the default value provided to the prompt is the key value 2 instead. </p>
<p>Special note: if I want to use a default value, then I have to specify not_persistent. If I don&#8217;t, then the default value is only good the first time the query is refreshed. From that point forward the last user selection will be used instead.</p>
<h3>What About Those {}?</h3>
<p>A reader with extremely good attention to detail will notice that the syntax I posted above does not match what was shown in the user manual. In order to get the object to parse I had to follow the exact syntax shown in the function help in Designer rather than what is in the documentation. What&#8217;s different? The code I used has curly braces { } around the value:key pair at the end. The curly braces are also used when providing a hard-coded list of values, so I guess that&#8217;s not too surprising.</p>
<h3>Conclusion</h3>
<p>The primary_key and default:key additions to the @prompt() syntax are quite powerful, and should be well-received by universe designers. I feel much more comfortable using something that is documented (even with slight errors) than using a feature that isn&#8217;t detailed in the documentation or help files anywhere. The concept of index awareness just became a lot more attractive with this addition.</p>
<p><em>This feature was one of several mentioned in my Designer Essentials presentation delivered at the 2008 GBN conference. This feature was covered on page 9.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagira.com/2008/11/01/designer-xi-3-new-feature-extended-prompt-syntax/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>GBN 2008 Conference Evaluations</title>
		<link>http://www.dagira.com/2008/10/30/gbn-2008-conference-evaluations/</link>
		<comments>http://www.dagira.com/2008/10/30/gbn-2008-conference-evaluations/#comments</comments>
		<pubDate>Thu, 30 Oct 2008 20:19:30 +0000</pubDate>
		<dc:creator>Dave Rathbun</dc:creator>
				<category><![CDATA[2008 GBN - Dallas]]></category>
		<category><![CDATA[GBN]]></category>

		<guid isPermaLink="false">http://www.dagira.com/?p=131</guid>
		<description><![CDATA[
I have been asked by a few different folks about evaluations for the conference, both from an attendee perspective and for speakers as well. For previous conferences conference attendees filled out evaluation forms before leaving the site (that&#8217;s how you got your conference t-shirt). For the GBN conference we didn&#8217;t do that. From what I [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/gbn/gbn_logo_150x62.png" width="150" height="62" border="0" class="right" alt="GBN Logo" title="GBN - Global Business Objects Network" /></p>
<p>I have been asked by a few different folks about evaluations for the conference, both from an attendee perspective and for speakers as well. For previous conferences conference attendees filled out evaluation forms before leaving the site (that&#8217;s how you got your conference t-shirt). For the GBN conference we didn&#8217;t do that. From what I hear, conference attendees will be soon receiving an email with a link to an online survey, at which point you will be able to provide any feedback about the overall conference.</p>
<p>I don&#8217;t know how much of the details for the conference feedback will be made public. Business Objects did not release the overall conference evaluation numbers to the public. I do know that every single comment will be read, categorized, and evaluated. This was the first year for a GBN-run conference and I think everyone recognized that there were some differences. The opportunity before us will be to sort out which differences were important, which should be repeated, and which should be fixed.</p>
<p>For example, one bit of feedback that I intend to provide is related to the room configuration. The room I was scheduled to speak in was quite large, and fairly deep. I don&#8217;t know how many rows of chairs there were, but it was more than a few. Yet there was no raised platform for the speaker in the front of the room. I am sure that impacted how visible I was in the back of the room. I imagine everyone could hear me, but hearing is not the same as hearing + seeing at the same time. I think for larger rooms we want to make sure we have elevated platforms next year.</p>
<p>Speakers, on the other hand, will be waiting a bit longer to get our feedback. I don&#8217;t have exact dates, but I am told that each speaker should be getting an email soon with more details on when we can expect to see our results. I know I look forward to seeing the numbers. I have had some great comments over the years, and I do strive for the best overall ratings that I can get.</p>
<p>Survey response percentages are typically very low. If you attended the conference and you&#8217;re reading this, I would encourage you to fill out the survey once you get the link. The function of the steering committee is to &#8220;steer&#8221; or guide in the desired direction. It is your voice that should determine that direction. Let&#8217;s hear it. <img src='http://www.dagira.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.dagira.com/2008/10/30/gbn-2008-conference-evaluations/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
