<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" version="2.0">
  <channel>
    <title>Miky Schreiber's Blog - BI|DataWarehousing</title>
    <link>http://www.miky-schreiber.com/Blog/</link>
    <description>Business Intelligence, Analysis Services, MDX, DataWarehousing and more...</description>
    <language>en-us</language>
    <copyright>Miky Schreiber</copyright>
    <lastBuildDate>Mon, 10 May 2010 12:57:55 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.9.6264.0</generator>
    <managingEditor>miky@zahav.net.il</managingEditor>
    <webMaster>miky@zahav.net.il</webMaster>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=5d896ea0-b01b-4de3-ae5c-e2e3733bd884</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,5d896ea0-b01b-4de3-ae5c-e2e3733bd884.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,5d896ea0-b01b-4de3-ae5c-e2e3733bd884.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=5d896ea0-b01b-4de3-ae5c-e2e3733bd884</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">From time to time I find myself writing
a hierarchial query in Oracle DB. It helps me a lot when I need to understand hierarchial
data, mostly resides in the source systems of the Datawarehouse. Yesterday I've
seen that a lot of my colleagues haven't heard about these kind of queries, even the
most experienced ones. So here is a tiny tutorial for this subject which you can go
back to any time. The important thing here is that you'll know that these kind of
queries exists even if you'll google it the next time you'll need it (search for "<a href="http://www.google.co.il/search?q=oracle+start+with">start
with</a>" or "<a href="http://www.google.co.il/search?q=oracle+connect+by">connect
by</a>").<br />
Let's say you have a table which looks like this:<br /><table border="1"><tbody><tr><td><u>Key</u></td><td><u>Father</u></td><td><u>Description</u></td></tr><tr><td><font size="2">1</font></td><td><font size="2">10</font></td><td><font size="2">Renault</font></td></tr><tr><td><font size="2">2</font></td><td><font size="2">20</font></td><td><font size="2">Jambo</font></td></tr><tr><td><font size="2">3</font></td><td><font size="2">20</font></td><td><font size="2">Airbus</font></td></tr><tr><td><font size="2">4</font></td><td><font size="2">10</font></td><td><font size="2">Hyundai</font></td></tr><tr><td><font size="2">5</font></td><td><font size="2">10</font></td><td><font size="2">Toyota</font></td></tr><tr><td><font size="2">6</font></td><td><font size="2">10</font></td><td><font size="2">Honda</font></td></tr><tr><td><font size="2">7</font></td><td><font size="2">20</font></td><td><font size="2">F16</font></td></tr><tr><td><font size="2">8</font></td><td><font size="2">20</font></td><td><font size="2">F15</font></td></tr><tr><td><font size="2">9</font></td><td><font size="2">10</font></td><td><font size="2">Alpha Romeo</font></td></tr><tr><td><font size="2">10</font></td><td><font size="2">-1</font></td><td><font size="2">Cars</font></td></tr><tr><td><font size="2">20</font></td><td><font size="2">-1</font></td><td><font size="2">Airplanes</font></td></tr><tr><td><font size="2">-1</font></td><td><font size="2">-99</font></td><td><font size="2">Transportation</font></td></tr></tbody></table><br />
You want to see the data in a tree form, meaning that you'll see Renault, its parent,
its grandparent and so on. All you need to write is the following query:<br /><br />
select * from MyTable<br />
start with KEY = 1<br />
connect by prior FATHER = KEY<br /><br />
That's it. The result is:<br /><table border="1"><tbody><tr><td><u>Key</u></td><td><u>Father</u></td><td><u>Description</u></td></tr><tr><td><font size="2">1</font></td><td><font size="2">10</font></td><td><font size="2">Renault</font></td></tr><tr><td><font size="2">10</font></td><td><font size="2">-1</font></td><td><font size="2">Cars</font></td></tr><tr><td><font size="2">-1</font></td><td><font size="2">-99</font></td><td><font size="2">Transportation</font></td></tr></tbody></table><br />
Note that the recursion stops only when it cannot find the next parent. In addition,
many times you'll want only one row from the tree (the root, its son or some other
criteria). In this case you can simply add a where clause to the query.<br />
Unfortunately, doing the same with SQL Server is much more <a href="http://dbbest.net/blog/?p=44">difficult</a> (tell
me if I'm wrong). 
<p>
Enjoy.
</p><img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=5d896ea0-b01b-4de3-ae5c-e2e3733bd884" /></body>
      <title>Hierarchial Queries in Oracle</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,5d896ea0-b01b-4de3-ae5c-e2e3733bd884.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,5d896ea0-b01b-4de3-ae5c-e2e3733bd884.aspx</link>
      <pubDate>Mon, 10 May 2010 12:57:55 GMT</pubDate>
      <description>From time to time I find myself writing a hierarchial query in Oracle DB. It helps me a lot when I need to understand hierarchial data, mostly resides&amp;nbsp;in the source systems of the Datawarehouse. Yesterday I've seen that a lot of my colleagues haven't heard about these kind of queries, even the most experienced ones. So here is a tiny tutorial for this subject which you can go back to any time. The important thing here is that you'll know that these kind of queries exists even if you'll google it the next time you'll need it (search for "&lt;a href="http://www.google.co.il/search?q=oracle+start+with"&gt;start
with&lt;/a&gt;" or "&lt;a href="http://www.google.co.il/search?q=oracle+connect+by"&gt;connect
by&lt;/a&gt;").&lt;br&gt;
Let's say you have a table which looks like this:&lt;br&gt;
&lt;table border=1&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;u&gt;Key&lt;/u&gt;&lt;/td&gt;
&lt;td&gt;
&lt;u&gt;Father&lt;/u&gt;&lt;/td&gt;
&lt;td&gt;
&lt;u&gt;Description&lt;/u&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;1&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;10&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;Renault&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;2&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;20&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;Jambo&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;3&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;20&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;Airbus&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;4&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;10&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;Hyundai&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;5&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;10&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;Toyota&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;6&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;10&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;Honda&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;7&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;20&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;F16&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;8&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;20&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;F15&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;9&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;10&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;Alpha Romeo&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;10&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;-1&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;Cars&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;20&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;-1&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;Airplanes&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;-1&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;-99&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;Transportation&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
You want to see the data in a tree form, meaning that you'll see Renault, its parent,
its grandparent and so on. All you need to write is the following query:&lt;br&gt;
&lt;br&gt;
select * from MyTable&lt;br&gt;
start with KEY = 1&lt;br&gt;
connect by prior FATHER = KEY&lt;br&gt;
&lt;br&gt;
That's it. The result is:&lt;br&gt;
&lt;table border=1&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;u&gt;Key&lt;/u&gt;&lt;/td&gt;
&lt;td&gt;
&lt;u&gt;Father&lt;/u&gt;&lt;/td&gt;
&lt;td&gt;
&lt;u&gt;Description&lt;/u&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;1&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;10&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;Renault&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;10&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;-1&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;Cars&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;font size=2&gt;-1&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;-99&lt;/font&gt;&lt;/td&gt;
&lt;td&gt;
&lt;font size=2&gt;Transportation&lt;/font&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
Note that the recursion stops only when it cannot find the next parent. In addition,
many times you'll want only one row from the tree (the root, its son or some other
criteria). In this case you can simply add a where clause to the query.&lt;br&gt;
Unfortunately, doing the same with SQL Server is much more &lt;a href="http://dbbest.net/blog/?p=44"&gt;difficult&lt;/a&gt; (tell
me if I'm wrong). 
&lt;p&gt;
Enjoy.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=5d896ea0-b01b-4de3-ae5c-e2e3733bd884" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,5d896ea0-b01b-4de3-ae5c-e2e3733bd884.aspx</comments>
      <category>BI;BI/DataWarehousing;BI/Oracle;Tips &amp; Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=6c28fd76-8c34-4ef0-8a42-ba2f267df8d3</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,6c28fd76-8c34-4ef0-8a42-ba2f267df8d3.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,6c28fd76-8c34-4ef0-8a42-ba2f267df8d3.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=6c28fd76-8c34-4ef0-8a42-ba2f267df8d3</wfw:commentRss>
      <title>History Browsing in OLAP and LastNonEmptyLeaf</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,6c28fd76-8c34-4ef0-8a42-ba2f267df8d3.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,6c28fd76-8c34-4ef0-8a42-ba2f267df8d3.aspx</link>
      <pubDate>Wed, 03 Mar 2010 12:34:48 GMT</pubDate>
      <description>&lt;img style="MARGIN: 0px 1em 1em" height="50%" src="http://www.miky-schreiber.com/Blog/content/binary/time.jpg" width="25%" align=left&gt; One
of the basic requirements of a modern BI system or Data Warehouse is to be non-volatile,
meaning that the DWH will save the history. In this post I'll explain how to implement
it in the DWH while assuming that the history can be changed and (the more interesting
part) how to implement it in Analysis Services.&lt;br&gt;
&lt;p&gt;
Before starting with history saving in the DWH,&amp;nbsp;I need to say that this has nothing
to do with Slowly Changing Dimensions. You can work with Type 1, 2 or 3. All you need
to take care of is that the fact table will be consistent with the dimension tables.
Assuming that the history can change (this is&amp;nbsp;the scenario&amp;nbsp;in my organization),
we need to extract all the fact data every time. If you work with staging level/environment/layer
you can use it to calculate which records has been changed or&amp;nbsp;inserted&amp;nbsp;and
only upsert them&amp;nbsp;to the DWH itself (it's more secure). In our case, we'll work
without such staging level so we need to load all the fact data in every load to the
DWH.
&lt;/p&gt;
&lt;p&gt;
Loading&amp;nbsp;the fact&amp;nbsp;in the ETL is very simple - we'll&amp;nbsp;save the&amp;nbsp;datetime
of the execution start, round it&amp;nbsp;and put it in every&amp;nbsp;row in the fact table.
We can call this field&amp;nbsp;CreateTime. You probably ask yourself why we need to round
it. The answer is that we don't want the time dimension to have every possible value
of datetime. It's huge and the users don't need that kind of accuracy. That's why
I round it in my projects to half-hour, meaning that 14:27 becomes 14:00 and 14:50
becomes 14:30. Let's look at an example of such fact table:
&lt;/p&gt;
&lt;p&gt;
&lt;table style="WIDTH: 389pt; BORDER-COLLAPSE: collapse" cellspacing=0 cellpadding=0 width=518 border=0 x:str&gt;
&lt;colgroup&gt;
&lt;col style="WIDTH: 50pt; mso-width-source: userset; mso-: 2450" width=67&gt;
&lt;col style="WIDTH: 63pt; mso-width-source: userset; mso-: 3072" span=2 width=84&gt;
&lt;col style="WIDTH: 53pt; mso-width-source: userset; mso-: 2560" span=2 width=70&gt;
&lt;col style="WIDTH: 107pt; mso-width-source: userset; mso: 5229" width=143&gt;
&lt;tbody&gt;
&lt;tr style="HEIGHT: 12.75pt" height=17&gt;
&lt;td class=xl22 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext 0.5pt solid; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 50pt; BORDER-BOTTOM: windowtext 0.5pt solid; HEIGHT: 12.75pt; BACKGROUND-: transparent" width=67 height=17&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;&lt;strong&gt;&lt;em&gt;&lt;u&gt;RowNum&lt;/u&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl22 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext 0.5pt solid; BORDER-LEFT: windowtext; WIDTH: 63pt; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" width=84&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;&lt;strong&gt;&lt;em&gt;&lt;u&gt;Dimension1&lt;/u&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/font&gt; 
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl22 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext 0.5pt solid; BORDER-LEFT: windowtext; WIDTH: 63pt; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" width=84&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;&lt;strong&gt;&lt;em&gt;&lt;u&gt;Dimension2&lt;/u&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/font&gt; 
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl22 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext 0.5pt solid; BORDER-LEFT: windowtext; WIDTH: 53pt; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" width=70&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;&lt;strong&gt;&lt;em&gt;&lt;u&gt;Measure1&lt;/u&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/font&gt; P&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl22 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext 0.5pt solid; BORDER-LEFT: windowtext; WIDTH: 53pt; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" width=70&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;&lt;strong&gt;&lt;em&gt;&lt;u&gt;Measure2&lt;/u&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/font&gt; P&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl23 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext 0.5pt solid; BORDER-LEFT: windowtext; WIDTH: 107pt; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" width=143&gt;
&lt;p align=center&gt;
&lt;strong&gt;&lt;em&gt;&lt;u&gt;&lt;font face=Arial color=#000000 size=2&gt;CreateTime&lt;/font&gt;&lt;/u&gt;&lt;/em&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="HEIGHT: 12.75pt" height=17&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext 0.5pt solid; BORDER-BOTTOM: windowtext 0.5pt solid; HEIGHT: 12.75pt; BACKGROUND-COLOR: transparent" height=17 x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;1&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;X&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;A&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;4&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;20&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl25 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;03/03/2010 15:00&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="HEIGHT: 12.75pt" height=17&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext 0.5pt solid; BORDER-BOTTOM: windowtext 0.5pt solid; HEIGHT: 12.75pt; BACKGROUND-COLOR: transparent" height=17 x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;2&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;X&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;B&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;56&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl26 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;strong&gt;&lt;font face=Arial color=#000000 size=2&gt;19&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl25 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;03/03/2010 15:00&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="HEIGHT: 12.75pt" height=17&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext 0.5pt solid; BORDER-BOTTOM: windowtext 0.5pt solid; HEIGHT: 12.75pt; BACKGROUND-COLOR: transparent" height=17 x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;3&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;Y&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;B&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;2&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;3&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl25 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;03/03/2010 15:00&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="HEIGHT: 12.75pt" height=17&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext 0.5pt solid; BORDER-BOTTOM: windowtext 0.5pt solid; HEIGHT: 12.75pt; BACKGROUND-COLOR: transparent" height=17 x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;4&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;Y&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;B&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl26 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;strong&gt;&lt;font face=Arial color=#000000 size=2&gt;1&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;10&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl25 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;03/03/2010 15:00&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="HEIGHT: 12.75pt" height=17&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext 0.5pt solid; BORDER-BOTTOM: windowtext 0.5pt solid; HEIGHT: 12.75pt; BACKGROUND-COLOR: transparent" height=17 x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;5&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;Y&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;C&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;7&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;5&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl25 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;03/03/2010 15:00&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="HEIGHT: 12.75pt" height=17&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext 0.5pt solid; BORDER-BOTTOM: windowtext 0.5pt solid; HEIGHT: 12.75pt; BACKGROUND-COLOR: transparent" height=17 x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;6&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;X&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;A&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;4&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;20&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl25 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;03/03/2010 15:30&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="HEIGHT: 12.75pt" height=17&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext 0.5pt solid; BORDER-BOTTOM: windowtext 0.5pt solid; HEIGHT: 12.75pt; BACKGROUND-COLOR: transparent" height=17 x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;7&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;X&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;B&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;56&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl26 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;strong&gt;&lt;font face=Arial color=#000000 size=2&gt;40&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl25 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;03/03/2010 15:30&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="HEIGHT: 12.75pt" height=17&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext 0.5pt solid; BORDER-BOTTOM: windowtext 0.5pt solid; HEIGHT: 12.75pt; BACKGROUND-COLOR: transparent" height=17 x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;8&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;Y&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;B&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;2&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;3&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl25 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;03/03/2010 15:30&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="HEIGHT: 12.75pt" height=17&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext 0.5pt solid; BORDER-BOTTOM: windowtext 0.5pt solid; HEIGHT: 12.75pt; BACKGROUND-COLOR: transparent" height=17 x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;9&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;Y&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;B&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl26 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;strong&gt;&lt;font face=Arial color=#000000 size=2&gt;10&lt;/font&gt;&lt;/strong&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;10&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl25 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;03/03/2010 15:30&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style="HEIGHT: 12.75pt" height=17&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext 0.5pt solid; BORDER-BOTTOM: windowtext 0.5pt solid; HEIGHT: 12.75pt; BACKGROUND-COLOR: transparent" height=17 x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;10&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;Y&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;C&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;7&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl24 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent" x:num&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;5&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;td class=xl25 style="BORDER-RIGHT: windowtext 0.5pt solid; BORDER-TOP: windowtext; BORDER-LEFT: windowtext; BORDER-BOTTOM: windowtext 0.5pt solid; BACKGROUND-COLOR: transparent"&gt;
&lt;p align=center&gt;
&lt;font face=Arial color=#000000 size=2&gt;03/03/2010 15:30&lt;/font&gt;
&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;
Here we can see two executions of the ETL: The first between 15:00 and 15:00, the
second between 15:31 and 15:59. Note the differences in rows 2 vs. 7 and 4 vs. 9.
This means that the source table(s) has changed between the executions.
&lt;/p&gt;
&lt;p&gt;
In the DWH, we create foreign keys from Dimension1 and Dimension2 to their dimension
tables. We'll also create FK between CreateTime and the time dimension. I won't get
into the time dimension design here, you can read about it&amp;nbsp;a &lt;a href="http://www.miky-schreiber.com/Blog/PermaLink,guid,73f9d050-05bd-4dc9-b719-ae9d256557b3.aspx"&gt;past
post&lt;/a&gt;. I assume that the time dimension has the hierarchy Year -&amp;gt; Month -&amp;gt;
Day -&amp;gt; Hour -&amp;gt; Half-Hour. It seems that now we have a good fact table for use
in Reporting Services (or any other reporting tool). Create a parameter called Extraction
Time/ETL Time and assign it values from distinct on CreateTime. The user can pick
a date and the report will filter on this date. Perfect.
&lt;/p&gt;
&lt;p&gt;
The problematic part starts in Analysis Services. &lt;strong&gt;Only one extraction time
can be the current member. There is no sense in summing or aggregating more than one
extraction time.&lt;/strong&gt; There are two ways to deal with it:
&lt;/p&gt;
&lt;u&gt;The wrong way&lt;/u&gt; - I'm writing&amp;nbsp;this down so you'll learn from this &lt;em&gt;design
mistake&lt;/em&gt;. We created a calculated member which takes the last extraction time: 
&lt;p&gt;
&lt;/p&gt;
&lt;p&gt;
Create Member CurrentCube.[Extraction Time]. [Calendar].[All].[Last Data Time]&lt;br&gt;
AS&lt;br&gt;
Tail ([Extraction Time].[Calendar].[HALF HOUR].Members,1).Item(0),&lt;br&gt;
Visible = 1; 
&lt;p&gt;
In every Panorama view, we sliced the Extraction time on the [Last Data Time] member,
which will show the user the data of the last ETL run. Our basic assumption was that
the user wants to see the current data and when he'll want to see the historical data
he will pick another member from the Extraction time dimension. This is the point
we missed and it soon&amp;nbsp; enough bumped into our face. 
&lt;p&gt;
We forgot that every system, even BI system which is built for analysts should be
intuitive and idiot-proof. The users picked members from the day level in the Extraction
time dimension. When we asked them why they did it they said that "we wanted to see
the data from 03/03/2010 and suddenly the numbers got bigger!". That happened, of
course, because the member 03/03/2010 is the sum of 03/03/2010 15:00 and 03/03/2010
15:30. The solution is that no matter which member the user picks in the Extraction
time dimension, he should see only one leaf (half-hour level) member at a time. This
takes us to 
&lt;p&gt;
&lt;u&gt;The right way&lt;/u&gt; - We set the [Last Data Time] member to be visible = 0 (I kept
it for debug purposes) and I written MDX script which I call NonLastEmptyLeaf. This
script makes sure that&amp;nbsp;no matter which member in the Extraction time hierarchy
will be picked, the user will be sliced only on the last non empty leaf. For example,
if the user picks 03/03/2010 he will see the data of 03/03/2010 15:30. This is what
will happen also when he'll slice on 03/2010, 2010 and even the [All] member. This
is the MDX script:&lt;br&gt;
&lt;br&gt;
Freeze([Extraction time].[Calendar].[All]);&lt;br&gt;
Scope(&lt;br&gt;
&amp;nbsp; Descendants (&lt;br&gt;
&amp;nbsp;&amp;nbsp; [Extraction time].[Calendar]. [All],&lt;br&gt;
&amp;nbsp;&amp;nbsp; 0,&lt;br&gt;
&amp;nbsp;&amp;nbsp; SELF_AND_AFTER&lt;br&gt;
&amp;nbsp; )&lt;br&gt;
);&lt;br&gt;
&amp;nbsp; this = Tail (&lt;br&gt;
&amp;nbsp;&amp;nbsp; Filter(&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Descendants(&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Extraction time]. [Calendar].CurrentMember,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Extraction time].[Calendar].[HALF HOUR],&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LEAVES&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; ),&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; [Measures].CurrentMember &amp;gt; 0&lt;br&gt;
&amp;nbsp;&amp;nbsp; ) 
&lt;br&gt;
&amp;nbsp; ).Item(0);&lt;br&gt;
End Scope;
&lt;/p&gt;
&lt;p&gt;
Now, there is no meaning of [Last Data Time] member because slicing on the [All] member
will show the current data, meaning that no slicing at all will show the current data
because [All] is the default member.
&lt;/p&gt;
&lt;p&gt;
To conclude,&amp;nbsp;history browsing can be dangerous if we let the users the option
to slice on more than one data time. The open question that I have is how can I prevent
the user from picking more than one member in this hierarchy in Panorama views? Should
I even try to do that or should I count on his minimal common sense?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=6c28fd76-8c34-4ef0-8a42-ba2f267df8d3" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,6c28fd76-8c34-4ef0-8a42-ba2f267df8d3.aspx</comments>
      <category>BI;BI/DataWarehousing;BI/MDX;BI/SQL Server 2005;BI/SQL Server 2005/Analysis Services;BI/SQL Server 2008;BI/SQL Server 2008/Analysis Services</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=3ded0f0b-56ab-4086-9a38-8ca0d784b6dd</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,3ded0f0b-56ab-4086-9a38-8ca0d784b6dd.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,3ded0f0b-56ab-4086-9a38-8ca0d784b6dd.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=3ded0f0b-56ab-4086-9a38-8ca0d784b6dd</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">Two weeks ago I did a talk about SCD. <a href="http://www.miky-schreiber.com/Blog/content/binary/Slowly%20Changing%20Dimensions.ppt">Here</a> is
the presentation.<br />
I think that even if you're doing BI (design or development) for quite a while you'll
find this presention resourceful and maybe you'll learn a thing or two...<br />
Have a nice learning!<img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=3ded0f0b-56ab-4086-9a38-8ca0d784b6dd" /></body>
      <title>Slowly Changing Dimensions Presentation</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,3ded0f0b-56ab-4086-9a38-8ca0d784b6dd.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,3ded0f0b-56ab-4086-9a38-8ca0d784b6dd.aspx</link>
      <pubDate>Tue, 13 Oct 2009 14:38:41 GMT</pubDate>
      <description>Two weeks ago I did a talk about SCD. &lt;a href="http://www.miky-schreiber.com/Blog/content/binary/Slowly%20Changing%20Dimensions.ppt"&gt;Here&lt;/a&gt; is
the presentation.&lt;br&gt;
I think that even if you're doing BI (design or development) for quite a while you'll
find this presention resourceful and maybe you'll learn a thing or two...&lt;br&gt;
Have a nice learning!&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=3ded0f0b-56ab-4086-9a38-8ca0d784b6dd" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,3ded0f0b-56ab-4086-9a38-8ca0d784b6dd.aspx</comments>
      <category>BI;BI/DataWarehousing</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=d8eb1331-dfd7-4c1a-823d-4e34c20565e3</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,d8eb1331-dfd7-4c1a-823d-4e34c20565e3.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,d8eb1331-dfd7-4c1a-823d-4e34c20565e3.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=d8eb1331-dfd7-4c1a-823d-4e34c20565e3</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Last August, I've seen an Informatica webinar featuring Dr. Ralph Kimball (you can
see it <a href="http://www12.informatica.com/livemeetings/Kimball_Webinar_Q109.asx">here</a>).
The topic of the webinar was "Reverse the flow of Data Warehouse Design to Ensure
Success". In order to make long things short, what he says is that in the DWH's first
steps you don't and can't know what are the full requirements. This is quite problematic,
because the first steps of the DWH - its design - are the most crucial steps, where
you take the most important decisions which will be hard to change later. His solution
is revolutionary and sounds a little bit hallucinatory - Start with the website. After
you have the front-end finished, whether it's a dashboard website or just a simple
tabular report, and you have the customer's approval, you can start the DWH design
and you know exactly what you should do and what you should not.
</p>
        <p>
Thinking of that, we decided that he's right but it's too much. The cost of building
a website with a data source behind it which will be changed 100 times in a short
period is very high. Instead, we're working in a defferent method - We are working
with <a href="http://en.wikipedia.org/wiki/Mockup">Mockups</a>.
</p>
        <p>
Our mockups are PowerPoint presentations which mock the dashboard website that will
be the project's front-end. We're using a lot of buttons and hyperlinks between the
different slides in order to create a feeling of a real website with navigation and
interactivity. When we show it to the customer and tell him that this is what his
dashboard will look like, at first he's very happy and then the new requirement's
phase begin: Can I have this button here? This one more slicer there? What about replacing
this chart with this one? etc. In PowerPoint presentation, making these changes is
very easy and after a couple of days we have a good understanding of how our front-end
will look like. Threfore, we fully understand how our DWH will look like. This
is a <strong>great</strong> method, I recommend you'll start using it in your next
project. Try and see for yourself!
</p>
There are some more points you need to know before starting using it: 
<ul><li>
You're not have to use Power Point for this. Visio and even Paint Brush can assist
you. Nevertheless, I recommend you to use a tool for this (remember that the mockup
will be changing a lot). There are <a href="http://www.google.co.il/search?q=visio+open+source+alternative">many
free &amp; open-source tools</a> to do it.</li><li>
You may consider to have the mockup to be your contract with the customer. On the
other hand, the final result may look a little bit different. You can draw everything
in PowerPoint but in the reality things may be hard to implement.</li><li>
After finishing the design phase, don't go over and over to the mockup to keep it
updated. Again - The reality is stronger than the first design. When the project will
be finished, no-one will care about the mockup.</li></ul><img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=d8eb1331-dfd7-4c1a-823d-4e34c20565e3" /></body>
      <title>Let's Mockup</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,d8eb1331-dfd7-4c1a-823d-4e34c20565e3.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,d8eb1331-dfd7-4c1a-823d-4e34c20565e3.aspx</link>
      <pubDate>Thu, 24 Sep 2009 11:49:44 GMT</pubDate>
      <description>&lt;p&gt;
Last August, I've seen an Informatica webinar featuring Dr. Ralph Kimball (you can
see it &lt;a href="http://www12.informatica.com/livemeetings/Kimball_Webinar_Q109.asx"&gt;here&lt;/a&gt;).
The topic of the webinar was "Reverse the flow of Data Warehouse Design to Ensure
Success". In order to make long things short, what he says is that in the DWH's first
steps you don't and can't know what are the full requirements. This is quite problematic,
because the first steps of the DWH - its design - are the most crucial steps, where
you take the most important decisions which will be hard to change later. His solution
is revolutionary and sounds a little bit hallucinatory - Start with the website. After
you have the front-end finished, whether it's a dashboard website or just a simple
tabular report, and you have the customer's approval, you can start the DWH design
and you know exactly what you should do and what you should not.
&lt;/p&gt;
&lt;p&gt;
Thinking of that, we decided that he's right but it's too much. The cost of building
a website with a data source behind it which will be changed 100 times in a short
period is very high. Instead, we're working in a defferent method - We are working
with &lt;a href="http://en.wikipedia.org/wiki/Mockup"&gt;Mockups&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Our mockups are PowerPoint presentations which mock the dashboard website that will
be the project's front-end. We're using a lot of buttons and hyperlinks between the
different slides in order to create a feeling of a real website with navigation and
interactivity. When we show it to the customer and tell him that this is what his
dashboard will look like, at first he's very happy and then the new requirement's
phase begin: Can I have this button here? This one more slicer there? What about replacing
this chart with this one? etc. In PowerPoint presentation, making these changes is
very easy and after a couple of days we have a good understanding of how our front-end
will look like. Threfore, we&amp;nbsp;fully understand how our DWH will look like. This
is a &lt;strong&gt;great&lt;/strong&gt; method, I recommend you'll start using it in your next
project. Try and see for yourself!
&lt;/p&gt;
There are some more points you need to know before starting using it: 
&lt;ul&gt;
&lt;li&gt;
You're not have to use Power Point for this. Visio and even Paint Brush can assist
you. Nevertheless, I recommend you to use a tool for this (remember that the mockup
will be changing a lot). There are &lt;a href="http://www.google.co.il/search?q=visio+open+source+alternative"&gt;many
free &amp;amp; open-source tools&lt;/a&gt; to do it.&lt;/li&gt;
&lt;li&gt;
You may consider to have the mockup to be your contract with the customer. On the
other hand, the final result may look a little bit different. You can draw everything
in PowerPoint but in the reality things may be hard to implement.&lt;/li&gt;
&lt;li&gt;
After finishing the design phase, don't go over and over to the mockup to keep it
updated. Again - The reality is stronger than the first design. When the project will
be finished, no-one will care about the mockup.&lt;/li&gt;
&lt;/ul&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=d8eb1331-dfd7-4c1a-823d-4e34c20565e3" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,d8eb1331-dfd7-4c1a-823d-4e34c20565e3.aspx</comments>
      <category>BI;BI/DataWarehousing</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=07245596-c190-485c-808f-7699f10cb928</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,07245596-c190-485c-808f-7699f10cb928.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,07245596-c190-485c-808f-7699f10cb928.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=07245596-c190-485c-808f-7699f10cb928</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <img style="MARGIN: 0px 1em 1em" src="http://www.miky-schreiber.com/blog/content/binary/oldpc.gif" align="left" />The
BI team and the source system team has a great bond between them. When the source
system's team wants to change the system's logic or the physical tables, they must
inform the BI team as soon as possible, because the BI team must change their system
too. Otherwise, the ETL will fail and the users will see old or no data, or in the
worse case the users will see incorrect data. 
<p>
On the other hand, when the BI system shows data which is not the same as the data
in the source system, the responsibility of showing that the BI system is OK is on
the BI team's shoulders. It needs to investigate the problem and see if the error
is on the BI side or in the source system side. Maybe there is no error at all and
the difference is caused by difference in the logic.
</p><p>
Sometimes, we (the BI team, of course) investigates the data problems and find that
the error resides in the source system itself. Then, we need to make sure that the
error is fixed in the system, whether by the IT staff or by the power users. The important
point here, and this is why I decided to write this post, is that the change must
be done first in the development environment of the source system. Then, we'll run
the ETL process and see that everything is fixed. This is important because sometimes
we think that the change will make things right and it's not. That's why everything
should be changed in the development environments first in both systems.
</p><p>
Only after we've seen that the data is fine, we can make the change in the production
environments. Last tip: <strong>Make sure that the change is also made in the source
system's production environment</strong>. Sometimes the time interval between these
events is long and the source system's team just forgets all about it. Write it down
as a task before going to production.
</p><img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=07245596-c190-485c-808f-7699f10cb928" /></body>
      <title>The BI Team and the Source System's Team Bond</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,07245596-c190-485c-808f-7699f10cb928.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,07245596-c190-485c-808f-7699f10cb928.aspx</link>
      <pubDate>Mon, 20 Jul 2009 09:24:28 GMT</pubDate>
      <description>&lt;img style="MARGIN: 0px 1em 1em" src="http://www.miky-schreiber.com/blog/content/binary/oldpc.gif" align=left&gt;The
BI team and the source system team has a great bond between them. When the source
system's team wants to change the system's logic or the physical tables, they must
inform the BI team as soon as possible, because the BI team must change their system
too. Otherwise, the ETL will fail and the users will see old or no data, or in the
worse case the users will see incorrect data. 
&lt;p&gt;
On the other hand, when the BI system shows data which is not the same as the data
in the source system, the responsibility of showing that the BI system is OK is on
the BI team's shoulders. It needs to investigate the problem and see if the error
is on the BI side or in the source system side. Maybe there is no error at all and
the difference is caused by difference in the logic.
&lt;/p&gt;
&lt;p&gt;
Sometimes, we (the BI team, of course) investigates the data problems and find that
the error resides in the source system itself. Then, we need to make sure that the
error is fixed in the system, whether by the IT staff or by the power users. The important
point here, and this is why I decided to write this post, is that the change must
be done first in the development environment of the source system. Then, we'll run
the ETL process and see that everything is fixed. This is important because sometimes
we think that the change will make things right and it's not. That's why everything
should be changed in the development environments first in both systems.
&lt;/p&gt;
&lt;p&gt;
Only after we've seen that the data is fine, we can make the change in the production
environments. Last tip: &lt;strong&gt;Make sure that the change is also made in the source
system's production environment&lt;/strong&gt;. Sometimes the time interval between these
events is long and the source system's team just forgets all about it. Write it down
as a task before going to production.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=07245596-c190-485c-808f-7699f10cb928" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,07245596-c190-485c-808f-7699f10cb928.aspx</comments>
      <category>BI;BI/DataWarehousing;Tips &amp; Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=d45d0c48-5f6d-4eba-804b-f94441619681</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,d45d0c48-5f6d-4eba-804b-f94441619681.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,d45d0c48-5f6d-4eba-804b-f94441619681.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=d45d0c48-5f6d-4eba-804b-f94441619681</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <img style="MARGIN: 0px 1em 1em 0px" src="http://www.miky-schreiber.com/Blog/content/binary/source.jpg" align="left" border="0" />
        <p>
          <font size="2">Last Week we had a funny case which took us much time to understand.</font>
        </p>
        <p>
          <font size="2">In our development environment, we like to have the same source data
for a long period of time. This way we're familiar with our data and we can expect
the numeric results in the higher layers (OLAP, dashboard, etc.). When we have a stable
environment and we think that our system gives the correct data, we ask our infrastructure
team to refresh our sources, meaning that they bring new production data to the development
environment.</font>
        </p>
        <p>
          <font size="2">The situation that we had last week is that we refreshed our sources
and from that point the data didn't make any sense. We asked the infrastructure team
if they're sure they refreshed the data and they said they are sure. We checked the
system and the data many times and seen that the data is different from what we had
but still it didn't make any sense.</font>
        </p>
        <p>
          <font size="2">After much frustration, one of us made a suggestion to write sql query
in this form:<br />
select max(some_date_field) from fact_table</font>
        </p>
        <p>
Then we were all amazed. After much time of sisyphean work we realized that our
data is not new at all. Moreover - our old data was old too. The maximum date in our
main fact table was <strong>half a year ago</strong>. The reason was that we took
our data from a legacy system which runs a job that exports their tables into
files, and our infrastructure team imports these files into our source tables. The
problem was that no-one ran the job so the files themselves were old, meaning that
our refresh activity means nothing.
</p>
        <p>
          <u>Conclusion</u>: Never trust your sources. Always run a sql query like mentioned
above to check that you have recent data and that the data you think you have is the
data you have. You can think of more queries that validates that what you have is
what you expect to have. Run them every morning to make sure you're ground is stable.
It's only a matter of seconds and it's worth it.
</p>
        <p>
May the source be with you.
</p>
        <img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=d45d0c48-5f6d-4eba-804b-f94441619681" />
      </body>
      <title>Don't Trust Your Sources</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,d45d0c48-5f6d-4eba-804b-f94441619681.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,d45d0c48-5f6d-4eba-804b-f94441619681.aspx</link>
      <pubDate>Mon, 20 Jul 2009 07:50:02 GMT</pubDate>
      <description>&lt;img style="MARGIN: 0px 1em 1em 0px" src="http://www.miky-schreiber.com/Blog/content/binary/source.jpg" align=left border=0&gt; 
&lt;p&gt;
&lt;font size=2&gt;Last Week we had a funny case which took us much time to understand.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2&gt;In our development environment, we like to have the same source data
for a long period of time. This way we're familiar with our data and we can expect
the numeric results in the higher layers (OLAP, dashboard, etc.). When we have a stable
environment and we think that our system gives the correct data, we ask our infrastructure
team to refresh our sources, meaning that they bring new production data to the development
environment.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2&gt;The situation that we had last week is that we refreshed our sources
and from that point the data didn't make any sense. We asked the infrastructure team
if they're sure they refreshed the data and they said they are sure. We checked the
system and the data many times and seen that the data is different from what we had
but still it didn't make any sense.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size=2&gt;After much frustration, one of us made a suggestion to write sql query
in this form:&lt;br&gt;
select max(some_date_field) from fact_table&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Then we were all&amp;nbsp;amazed. After much time of sisyphean work we realized that our
data is not new at all. Moreover - our old data was old too. The maximum date in our
main fact table was &lt;strong&gt;half a year ago&lt;/strong&gt;. The reason was that we took
our data from a legacy system which runs a job that&amp;nbsp;exports their tables into
files, and our infrastructure team imports these files into our source tables. The
problem was that no-one ran the job so the files themselves were old, meaning that
our refresh activity means nothing.
&lt;/p&gt;
&lt;p&gt;
&lt;u&gt;Conclusion&lt;/u&gt;: Never trust your sources. Always run a sql query like mentioned
above to check that you have recent data and that the data you think you have is the
data you have. You can think of more queries that validates that what you have is
what you expect to have. Run them every morning to make sure you're ground is stable.
It's only a matter of seconds and it's worth it.
&lt;/p&gt;
&lt;p&gt;
May the source be with you.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=d45d0c48-5f6d-4eba-804b-f94441619681" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,d45d0c48-5f6d-4eba-804b-f94441619681.aspx</comments>
      <category>BI;BI/DataWarehousing;Tips &amp; Tricks</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=e8983b76-ab68-4cf3-824b-77b340acc19c</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,e8983b76-ab68-4cf3-824b-77b340acc19c.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,e8983b76-ab68-4cf3-824b-77b340acc19c.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=e8983b76-ab68-4cf3-824b-77b340acc19c</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">Very easy. In Sql Server:<br />
Select top n * from my_table<br />
In Oracle:<br />
Select * from my_table where rownum &lt;= n<br /><p>
It can be very useful in many many cases. For example, you're designing DWH over a
system and you're looking at a certain field in one of its tables. You want to know
which values this field contains, but fetching "select distinct my_field from my_table"
takes too much time. Instead, if you <strike>believe</strike> know that the data is
well distributed, you can use "select distinct my_field from my_table where rownum
&lt;= n". Use 1000 for n in the first trial and add one zero in the end of the number
n every time until you got a query that takes too much time than you want to wait. after
you got the n you can live with, can use the values you have in your query result.
</p><img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=e8983b76-ab68-4cf3-824b-77b340acc19c" /></body>
      <title>Fetching N Rows In Sql Server and Oracle</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,e8983b76-ab68-4cf3-824b-77b340acc19c.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,e8983b76-ab68-4cf3-824b-77b340acc19c.aspx</link>
      <pubDate>Tue, 07 Apr 2009 19:54:28 GMT</pubDate>
      <description>Very easy. In Sql Server:&lt;br&gt;
Select top n * from my_table&lt;br&gt;
In Oracle:&lt;br&gt;
Select * from my_table where rownum &amp;lt;= n&lt;br&gt;
&lt;p&gt;
It can be very useful in many many cases. For example, you're designing DWH over a
system and you're looking at a certain field in one of its tables. You want to know
which values this field contains, but fetching "select distinct my_field from my_table"
takes too much time. Instead, if you &lt;strike&gt;believe&lt;/strike&gt; know that the data is
well distributed, you can use "select distinct my_field from my_table where rownum
&amp;lt;= n". Use 1000 for n in the first trial and add one zero in the end of the number
n every time until you got a query that takes too much time than you want to wait.&amp;nbsp;after
you&amp;nbsp;got the n you can live with, can use the values you have in your query result.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=e8983b76-ab68-4cf3-824b-77b340acc19c" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,e8983b76-ab68-4cf3-824b-77b340acc19c.aspx</comments>
      <category>BI;BI/DataWarehousing;BI/SQL Server 2005;BI/SQL Server 2008;BI/Oracle</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=cbc9ec2a-6745-411d-ba63-19561dc9f411</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,cbc9ec2a-6745-411d-ba63-19561dc9f411.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,cbc9ec2a-6745-411d-ba63-19561dc9f411.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=cbc9ec2a-6745-411d-ba63-19561dc9f411</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
There are some things you can only learn in the hard way. It didn't happenned
to me personally but to my team friends, so I consider it as it is my bad.
</p>
        <p>
We upgraded our ETL tool - Informatica, from version 8.5 to 8.6. We had to run
some tests to see that the results are the same. So, what we did is to save the result
table from 8.5 in Excel, save the result table from 8.6 in Excel and then compare
them using Excel-built-in functions. The only problem is we didn't pay attention to
the places where zero and null interchanged. This happened because the two versions
act differently where null values take places in aggregation functions. For example,
when there is a sum function and it aggregates only on null values. In one version
the output is zero and in the other the output is null... 
</p>
        <p>
This can also happen in other tools and technology. For example, in OLAP cubes the
difference between zero and null is the difference between seeing the member of the
dimension on the screen and not knowing of its existence.
</p>
        <p>
For conclusion, always be aware to this point and don't forget to check it.
</p>
        <img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=cbc9ec2a-6745-411d-ba63-19561dc9f411" />
      </body>
      <title>The Difference between null and zero</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,cbc9ec2a-6745-411d-ba63-19561dc9f411.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,cbc9ec2a-6745-411d-ba63-19561dc9f411.aspx</link>
      <pubDate>Sun, 22 Mar 2009 21:09:59 GMT</pubDate>
      <description>&lt;p&gt;
There are some things you can only learn&amp;nbsp;in&amp;nbsp;the hard way. It didn't happenned
to me personally but to my team friends, so I consider it as it is my bad.
&lt;/p&gt;
&lt;p&gt;
We upgraded our ETL tool&amp;nbsp;- Informatica, from version 8.5 to 8.6. We had to&amp;nbsp;run
some tests to see that the results are the same. So, what we did is to save the result
table from 8.5 in Excel, save the result table from 8.6 in Excel and then compare
them using Excel-built-in functions. The only problem is we didn't pay attention to
the places where zero and null interchanged. This happened because the two versions
act differently where null values take places in aggregation functions. For example,
when there is a sum function and it aggregates only on null values. In one version
the output is zero and in the other the output is null... 
&lt;/p&gt;
&lt;p&gt;
This can also happen in other tools and technology. For example, in OLAP cubes the
difference between zero and null is the difference between seeing the member of the
dimension on the screen and not knowing of its existence.
&lt;/p&gt;
&lt;p&gt;
For conclusion, always be aware to this point and don't forget to check it.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=cbc9ec2a-6745-411d-ba63-19561dc9f411" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,cbc9ec2a-6745-411d-ba63-19561dc9f411.aspx</comments>
      <category>BI;BI/DataWarehousing;BI/Informatica;BI/SQL Server 2005;BI/SQL Server 2005/Analysis Services;BI/SQL Server 2008;BI/SQL Server 2008/Analysis Services</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=f5f76417-9128-4fd7-a8d6-ba60619df30e</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,f5f76417-9128-4fd7-a8d6-ba60619df30e.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,f5f76417-9128-4fd7-a8d6-ba60619df30e.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=f5f76417-9128-4fd7-a8d6-ba60619df30e</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
This month we're really busy with a very important project and a short schedule. This
made me think of ideas for agile development for BI, but I'll leave it for other time
for now. In order to make us better BI developers, I decided to take one <a href="http://www.pragprog.com/the-pragmatic-programmer/extracts/tips">Pragmatic
Programmer</a> principle and use it. I took one of the most important (for
my opinion) principles - DRY (Don't Repeat Yourself). The DRY principle says that
"Every piece of knowledge must have a single, unambiguous, authoritative representation
within a system". In classic programming it's simple to use: Use methods and generic
classes to implements logic that will repeat itself in the project. But how do you
do it in BI development? Here are some ideas I thought and even implemented some of
them in my environment. Every layer/step in the BI development has it's own bulletin.
I'll be happy to hear more from you.
</p>
        <ul>
          <li>
First of all - use functions in your DataWarehouse's <strong>database</strong>. Do
it as much as you can. Do not repeat any logic twice or more, no matter if it's in
procedures, views or even CLR functions.</li>
          <li>
We all have much logic that repeats itself in the <strong>ETL</strong> process. For
example, we found ourselves doing over and over the next process: When we build a
fact table, we take every cell that points to a dimension table by a foreign
key and "looking up" if it's found in the dimension table. If it's not there we replace
it with Undefined, UD or null. That makes us feel very bad because we feel that we're
doing the same all the time and it gives us the feeling of machines rather than programmers.
The solution for this problem (and many other) is to build our own tasks (in SSIS)
or transformations (in SSIS &amp; Informatica). <a href="http://sqlblog.com/blogs/alberto_ferrari/default.aspx">Alberto
Ferrari</a> did a beautiful work in this field in SSIS. I'll add some transformations
of my own once I'll have release-ready versions of them.</li>
          <li>
My co-workers just loves the Calculated Member feature in the <strong>Data Source
View in SSAS</strong>. In enables them to make a new column without making a
view and with no touch in the underlying database. The problem here is that after
a while we have a LOT of calculated members, many of them repeats themselves and when
you look for logic you lost, you can look for hours in the never-ending
DSV. The solution here is not using calculated members at all. Put all your logic
in the database (and as I said - in functions). The only place where you should
use calculated members is where you must - when you have no write permission
to the DataWarehouse or when you build your DSV over an operative database and you
don't have write permissions.</li>
          <li>
The same is with Names Queries in the <strong>Data Source View in SSAS</strong>. Don't
use it.</li>
          <li>
There's much logic that you can do only in <strong>MDX</strong>. Here, the problem
is that MDX scripts are defined over cubes and not over dimensions, meaning that if
a dimension has MDX logic you have to repeat it in every cube's MDX script. The
solution is to add the MDX programically using AMO. Every time the ETL process ends,
it should run a program that takes the MDX script from a single file and place it
in every relevant cube. I know it sounds a little bit wacky and I even didn't do it
myself, but for what I know, it's the only solutions for DRY in MDX.</li>
        </ul>
        <p>
As I said, I'll love to hear your ideas about this topic.
</p>
        <img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=f5f76417-9128-4fd7-a8d6-ba60619df30e" />
      </body>
      <title>DRY Principle in BI Development</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,f5f76417-9128-4fd7-a8d6-ba60619df30e.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,f5f76417-9128-4fd7-a8d6-ba60619df30e.aspx</link>
      <pubDate>Fri, 17 Oct 2008 12:46:22 GMT</pubDate>
      <description>&lt;p&gt;
This month we're really busy with a very important project and a short schedule. This
made me think of ideas for agile development for BI, but I'll leave it for other time
for now. In order to make us better BI developers, I decided to take one &lt;a href="http://www.pragprog.com/the-pragmatic-programmer/extracts/tips"&gt;Pragmatic
Programmer&lt;/a&gt; principle and use it. I took&amp;nbsp;one of the&amp;nbsp;most important (for
my opinion) principles - DRY (Don't Repeat Yourself). The DRY principle says that
"Every piece of knowledge must have a single, unambiguous, authoritative representation
within a system". In classic programming it's simple to use: Use methods and generic
classes to implements logic that will repeat itself in the project. But how do you
do it in BI development? Here are some ideas I thought and even implemented some of
them in my environment. Every layer/step in the BI development has it's own bulletin.
I'll be happy to hear more from you.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
First of all - use functions in your DataWarehouse's &lt;strong&gt;database&lt;/strong&gt;. Do
it as much as you can. Do not repeat any logic twice or more, no matter if it's in
procedures, views or even CLR functions.&lt;/li&gt;
&lt;li&gt;
We all have much logic that repeats itself in the &lt;strong&gt;ETL&lt;/strong&gt; process. For
example, we found ourselves doing over and over the next process: When we build a
fact table, we take every cell that points to a dimension table&amp;nbsp;by a foreign
key and "looking up" if it's found in the dimension table. If it's not there we replace
it with Undefined, UD or null. That makes us feel very bad because we feel that we're
doing the same all the time and it gives us the feeling of machines rather than programmers.
The solution for this problem (and many other) is to build our own tasks (in SSIS)
or transformations (in SSIS &amp;amp; Informatica). &lt;a href="http://sqlblog.com/blogs/alberto_ferrari/default.aspx"&gt;Alberto
Ferrari&lt;/a&gt; did a beautiful work in this field in SSIS. I'll add some transformations
of my own once I'll have release-ready versions of them.&lt;/li&gt;
&lt;li&gt;
My co-workers just loves the Calculated Member feature in the &lt;strong&gt;Data Source
View in SSAS&lt;/strong&gt;. In enables them to&amp;nbsp;make a new column without making a
view and with no touch in the underlying database. The problem here is that after
a while we have a LOT of calculated members, many of them repeats themselves and when
you look for&amp;nbsp;logic you lost,&amp;nbsp;you can look for hours in the never-ending
DSV. The solution here is not using calculated members at all. Put all your logic
in the database (and as I said - in functions). The only place where you&amp;nbsp;should
use calculated members is where you must - when you have no write&amp;nbsp;permission
to the DataWarehouse or when you build your DSV over an operative database and you
don't have write permissions.&lt;/li&gt;
&lt;li&gt;
The same is with Names Queries in the &lt;strong&gt;Data Source View in SSAS&lt;/strong&gt;. Don't
use it.&lt;/li&gt;
&lt;li&gt;
There's much logic that you can do only in &lt;strong&gt;MDX&lt;/strong&gt;. Here, the problem
is that MDX scripts are defined over cubes and not over dimensions, meaning that if
a dimension has&amp;nbsp;MDX logic you have to repeat it in every cube's MDX script. The
solution is to add the MDX programically using AMO. Every time the ETL process ends,
it should run a program that takes the MDX script from a single file and place it
in every relevant cube. I know it sounds a little bit wacky and I even didn't do it
myself, but for what I know, it's the only solutions for DRY in MDX.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
As I said, I'll love to hear your ideas about this topic.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=f5f76417-9128-4fd7-a8d6-ba60619df30e" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,f5f76417-9128-4fd7-a8d6-ba60619df30e.aspx</comments>
      <category>BI;BI/DataWarehousing</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=604f84c5-6ec5-44ab-9484-2f65a913f721</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,604f84c5-6ec5-44ab-9484-2f65a913f721.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,604f84c5-6ec5-44ab-9484-2f65a913f721.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=604f84c5-6ec5-44ab-9484-2f65a913f721</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">I'll start from the bottom line: If you
create your Data Warehouse and you follow the DW rules, you're life will be easy (assuming
you know the semantics and the way to build a good and correct DW).<br />
In our case, if you have a dimension and you want to make a Parent-Child hierarchy,
your life will be easy if you built the dimension's table in the right way.<br /><br />
For example, let's look at a simple Time dimension:<br /><p></p><table border="1" height="107" width="285"><tbody><tr><td><b>Time_Key</b></td><td><b>Day</b></td><td><b>Month</b></td><td><b>Quarter</b></td><td><b>Year</b></td><td valign="top"><b>Level_Num<br /></b></td></tr><tr><td valign="top">
01012008<br /></td><td valign="top">
01<br /></td><td valign="top">
01<br /></td><td valign="top">
1<br /></td><td valign="top">
2008<br /></td><td valign="top">
1<br /></td></tr><tr><td valign="top">
30122008<br /></td><td valign="top">
30<br /></td><td valign="top">
12<br /></td><td valign="top">
4<br /></td><td valign="top">
2008<br /></td><td valign="top">
1<br /></td></tr><tr><td valign="top">
01/2008<br /></td><td valign="top"><br /></td><td valign="top">
01<br /></td><td valign="top">
1<br /></td><td valign="top">
2008<br /></td><td valign="top">
2<br /></td></tr><tr><td valign="top">
12/2008<br /></td><td valign="top"><br /></td><td valign="top">
12<br /></td><td valign="top">
4<br /></td><td valign="top">
2008<br /></td><td valign="top">
2<br /></td></tr><tr><td valign="top">
Q1/2008<br /></td><td valign="top"><br /></td><td valign="top"><br /></td><td valign="top">
1<br /></td><td valign="top">
2008<br /></td><td valign="top">
3<br /></td></tr><tr><td valign="top">
Q4/2008<br /></td><td valign="top"><br /></td><td valign="top"><br /></td><td valign="top">
4<br /></td><td valign="top">
2008<br /></td><td valign="top">
3<br /></td></tr><tr><td valign="top">
2008<br /></td><td valign="top"><br /></td><td valign="top"><br /></td><td valign="top"><br /></td><td valign="top">
2008<br /></td><td valign="top">
4<br /></td></tr></tbody></table><br />
As you can see, this time dimension's table contains the days 01/01/2008 and 30/12/2008
and their parents in the levels: month, quarter and year.<br />
Now, let's say that I need to take this dimension and make it a Parent-Child table.
This is very simple. Just create a view with one new column which will be the parent
column. This is the new column's code (in Pseudo-SQL):<br />
if (level_num = 1) then Month + "/" + Year<br />
else if (level_num = 2) then "Q" + Quarter + "/" + Year<br />
else if (level_num = 3) then Year<br />
else null<br /><br />
The result:<br /><br /><table border="1" height="107" width="285"><tbody><tr><td><b>Time_Key</b></td><td><b>Day</b></td><td><b>Month</b></td><td><b>Quarter</b></td><td><b>Year</b></td><td valign="top"><b>Level_Num<br /></b></td><td valign="top"><b>Parent</b><br /></td></tr><tr><td valign="top">
01012008<br /></td><td valign="top">
01<br /></td><td valign="top">
01<br /></td><td valign="top">
1<br /></td><td valign="top">
2008<br /></td><td valign="top">
1<br /></td><td valign="top">
01<br /></td></tr><tr><td valign="top">
30122008<br /></td><td valign="top">
30<br /></td><td valign="top">
12<br /></td><td valign="top">
4<br /></td><td valign="top">
2008<br /></td><td valign="top">
1<br /></td><td valign="top">
30<br /></td></tr><tr><td valign="top">
01/2008<br /></td><td valign="top"><br /></td><td valign="top">
01<br /></td><td valign="top">
1<br /></td><td valign="top">
2008<br /></td><td valign="top">
2<br /></td><td valign="top">
1<br /></td></tr><tr><td valign="top">
12/2008<br /></td><td valign="top"><br /></td><td valign="top">
12<br /></td><td valign="top">
4<br /></td><td valign="top">
2008<br /></td><td valign="top">
2<br /></td><td valign="top">
4<br /></td></tr><tr><td valign="top">
Q1/2008<br /></td><td valign="top"><br /></td><td valign="top"><br /></td><td valign="top">
1<br /></td><td valign="top">
2008<br /></td><td valign="top">
3<br /></td><td valign="top">
2008<br /></td></tr><tr><td valign="top">
Q4/2008<br /></td><td valign="top"><br /></td><td valign="top"><br /></td><td valign="top">
4<br /></td><td valign="top">
2008<br /></td><td valign="top">
3<br /></td><td valign="top">
2008<br /></td></tr><tr><td valign="top">
2008<br /></td><td valign="top"><br /></td><td valign="top"><br /></td><td valign="top"><br /></td><td valign="top">
2008<br /></td><td valign="top">
4<br /></td><td valign="top"><i>null</i><br /></td></tr></tbody></table><br />
This is it. Now, in your OLAP DB, just configure the new column as the parent and
you have a Parent-Child hierarchy. In Analysis Services you even don't have to create
a view. In the Data Source View you can add a named calculation and put your code
there.<br /><br />
See? When you create your DW according to its rules, the life is easier. In this example,
if you created rows for every level in the hierarchy and created a descriptive key
- everything is great.<br />
This can help you in many scenarios. For example, when you find that your dimension
is not balanced then you might want to make it a parent-child, so you won't have many
pseudo-levels when the only relevant member is the leaf. Otherwise, this can be very
annoying to your user. In SSAS, make sure you don't use it too much, because it is
bad for performance.<br /><img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=604f84c5-6ec5-44ab-9484-2f65a913f721" /></body>
      <title>Parent-Child Dimension in a correct DW? Easy.</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,604f84c5-6ec5-44ab-9484-2f65a913f721.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,604f84c5-6ec5-44ab-9484-2f65a913f721.aspx</link>
      <pubDate>Tue, 22 Apr 2008 18:06:32 GMT</pubDate>
      <description>I'll start from the bottom line: If you create your Data Warehouse and you follow the DW rules, you're life will be easy (assuming you know the semantics and the way to build a good and correct DW).&lt;br&gt;
In our case, if you have a dimension and you want to make a Parent-Child hierarchy,
your life will be easy if you built the dimension's table in the right way.&lt;br&gt;
&lt;br&gt;
For example, let's look at a simple Time dimension:&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;table border="1" height="107" width="285"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;b&gt;Time_Key&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;
&lt;b&gt;Day&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;
&lt;b&gt;Month&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;
&lt;b&gt;Quarter&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;
&lt;b&gt;Year&lt;/b&gt;&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;b&gt;Level_Num&lt;br&gt;
&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
01012008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
01&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
01&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
1&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
1&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
30122008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
30&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
12&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
4&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
1&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
01/2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
01&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
1&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
12/2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
12&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
4&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
Q1/2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
1&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
3&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
Q4/2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
4&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
3&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
4&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
As you can see, this time dimension's table contains the days 01/01/2008 and 30/12/2008
and their parents in the levels: month, quarter and year.&lt;br&gt;
Now, let's say that I need to take this dimension and make it a Parent-Child table.
This is very simple. Just create a view with one new column which will be the parent
column. This is the new column's code (in Pseudo-SQL):&lt;br&gt;
if (level_num = 1) then Month + "/" + Year&lt;br&gt;
else if (level_num = 2) then "Q" + Quarter + "/" + Year&lt;br&gt;
else if (level_num = 3) then Year&lt;br&gt;
else null&lt;br&gt;
&lt;br&gt;
The result:&lt;br&gt;
&lt;br&gt;
&lt;table border="1" height="107" width="285"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;b&gt;Time_Key&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;
&lt;b&gt;Day&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;
&lt;b&gt;Month&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;
&lt;b&gt;Quarter&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;
&lt;b&gt;Year&lt;/b&gt;&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;b&gt;Level_Num&lt;br&gt;
&lt;/b&gt;&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;b&gt;Parent&lt;/b&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
01012008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
01&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
01&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
1&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
1&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
01&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
30122008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
30&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
12&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
4&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
1&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
30&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
01/2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
01&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
1&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
1&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
12/2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
12&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
4&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
4&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
Q1/2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
1&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
3&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
Q4/2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
4&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
3&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
2008&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
4&lt;br&gt;
&lt;/td&gt;
&lt;td valign="top"&gt;
&lt;i&gt;null&lt;/i&gt;
&lt;br&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br&gt;
This is it. Now, in your OLAP DB, just configure the new column as the parent and
you have a Parent-Child hierarchy. In Analysis Services you even don't have to create
a view. In the Data Source View you can add a named calculation and put your code
there.&lt;br&gt;
&lt;br&gt;
See? When you create your DW according to its rules, the life is easier. In this example,
if you created rows for every level in the hierarchy and created a descriptive key
- everything is great.&lt;br&gt;
This can help you in many scenarios. For example, when you find that your dimension
is not balanced then you might want to make it a parent-child, so you won't have many
pseudo-levels when the only relevant member is the leaf. Otherwise, this can be very
annoying to your user. In SSAS, make sure you don't use it too much, because it is
bad for performance.&lt;br&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=604f84c5-6ec5-44ab-9484-2f65a913f721" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,604f84c5-6ec5-44ab-9484-2f65a913f721.aspx</comments>
      <category>BI/DataWarehousing</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=7473180e-117f-447f-b84c-38d91bbe3374</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,7473180e-117f-447f-b84c-38d91bbe3374.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,7473180e-117f-447f-b84c-38d91bbe3374.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=7473180e-117f-447f-b84c-38d91bbe3374</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Although SSAS willl let you use them, some other application such as Panorama won't
function properly. I'll give one example: When you perform Drillthrough in Panorama,
on the fly the engine gererates a web page that will take the user to the next view.
The next view will be sliced as the current view, so this web page needs to pass the
dimensions parameter (meaning - the current slices). That's why this web page contains
this line:
</p>
        <p>
AttachParameters("Slicers","%Slicers%")
</p>
        <p>
A big problem will occur if one of the sliced dimensions will be sliced on a member
with a name that contains inverted commas ("). The JavaScript will result an error
because there are three inverted commas in the second parameter of the line. This
is only one example of what can happen in a BI consumer program if you'll use special
characters in member names. So - be careful not to pass these characters from the
DW (build the ETL so it will drop these characters) or giving those names in SSAS,
such as the All member name.
</p>
        <img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=7473180e-117f-447f-b84c-38d91bbe3374" />
      </body>
      <title>Do Not Use Special Characters in DW &amp; SSAS</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,7473180e-117f-447f-b84c-38d91bbe3374.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,7473180e-117f-447f-b84c-38d91bbe3374.aspx</link>
      <pubDate>Tue, 15 Jan 2008 14:08:32 GMT</pubDate>
      <description>&lt;p&gt;
Although SSAS willl let you use them, some other application such as Panorama won't
function properly. I'll give one example: When you perform Drillthrough in Panorama,
on the fly the engine gererates a web page that will take the user to the next view.
The next view will be sliced as the current view, so this web page needs to pass the
dimensions parameter (meaning - the current slices). That's why this web page contains
this line:
&lt;/p&gt;
&lt;p&gt;
AttachParameters("Slicers","%Slicers%")
&lt;/p&gt;
&lt;p&gt;
A big problem will occur if one of the sliced dimensions will be sliced on a member
with a name that contains inverted commas ("). The JavaScript will result an error
because there are three inverted commas in the second parameter of the line. This
is only one example of what can happen in a BI consumer program if you'll use special
characters in member names. So - be careful not to pass these characters from the
DW (build the ETL so it will drop these characters) or giving those names in SSAS,
such as the All member name.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=7473180e-117f-447f-b84c-38d91bbe3374" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,7473180e-117f-447f-b84c-38d91bbe3374.aspx</comments>
      <category>BI;BI/DataWarehousing;BI/Panorama;BI/SQL Server 2005;BI/SQL Server 2005/Analysis Services;BI/SQL Server 2008;BI/SQL Server 2008/Analysis Services</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=2efa7c5b-826e-43c4-af42-5608fdd6c188</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,2efa7c5b-826e-43c4-af42-5608fdd6c188.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,2efa7c5b-826e-43c4-af42-5608fdd6c188.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=2efa7c5b-826e-43c4-af42-5608fdd6c188</wfw:commentRss>
      <slash:comments>5</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I feel like I don't have the right to write about it after so many bits of information
were moving in the web about this subject but I would like to add my point of view
(or in fact - my point of code). First of all, I must mention some of those who written
about this subject before me. Mosha Pasumansky wrote a long <a href="http://sqljunkies.com/WebLog/mosha/archive/2007/05/22/current_date_mdx.aspx">post</a> about
it in last may. This post contains some ideas of how to come along with this problem,
but none of them is perfect. In fact (as always) - there is no perfect solution
for this problem. Another important source of knowledge can be found <a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=346119&amp;SiteID=1">here</a> in
the MSDN forums, where Chris Webb, Thomas Pagel and others discussed it. Now,
I would like to add my solution. Take it or leave it - your choice.
</p>
        <p>
First of all, create a column in the time dimension that will be the current day indicator.
Thanks to the Data Source View or the UDM approach of SSAS 2005 you don't have to
change the relational table itself. Just add a named calculation in the DSV with expression
that will be 1 for the row of the current day and null or zero for the others. The
expression syntax itself depends on the underlying DB so I won't write it here, but
it's very simple. Add this column as an attribute (let's call it CurrentDayInd) in
the dimension structure and select its AttributeVisible propertiey to false. That's
because we don't need such Attribute Hierarchy in our time dimension. After that,
create a new User Hierarchy (you can call it Current Day), where the first level in
it will be CurrentDayInd and after it place the day (key) attribute.
</p>
        <p>
Now, what we have here? We have a hierarchy (Current Day) with two members - 1 and
zero. The 1 member has only one child which is the current day. Link that member to
your regular hierarchy (it's called YSQMD at my place) and here you have it. For example,
you can use it that way in the MDX script:
</p>
        <p>
Create Set [Last 30 Days] as<br />
LinkMember([Time].[Current Day].[CurrentDayInd].&amp;[1].Children.Item(0),[Time].[YSQMD])<br />
:<br />
LinkMember([Time].[Current Day].[CurrentDayInd].&amp;[1].Children.Item(0),[Time].[YSQMD]).Lag(30);
</p>
        <p>
I think that this solution is good and elegant. First of all, you don't have to use
external functions such as Now(). The second pro is that we use the native OLAP mechanism
which saves time and makes the queries run faster. Believe me, you'll feel the difference
with big cubes. The last thing is that this solution is easy to understand (at least
I think so) and it is easy for maintenance. The big con is that you have to process
this dimension (and related cubes) every day. I don't think that it's so bad because
most of the organizations do make process every day.
</p>
        <p>
          <br />
 
</p>
        <img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=2efa7c5b-826e-43c4-af42-5608fdd6c188" />
      </body>
      <title>Getting the Current Day in MDX</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,2efa7c5b-826e-43c4-af42-5608fdd6c188.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,2efa7c5b-826e-43c4-af42-5608fdd6c188.aspx</link>
      <pubDate>Tue, 08 Jan 2008 20:39:58 GMT</pubDate>
      <description>&lt;p&gt;
I feel like I don't have the right to write about it after so many bits of information
were moving in the web about this subject but I would like to add my point of view
(or in fact - my point of code). First of all, I must mention some of those who written
about this subject before me. Mosha Pasumansky wrote a long &lt;a href="http://sqljunkies.com/WebLog/mosha/archive/2007/05/22/current_date_mdx.aspx"&gt;post&lt;/a&gt; about
it in last may. This post contains some ideas of how to come along with this problem,
but none of them is perfect. In fact (as always) - there is no perfect&amp;nbsp;solution
for this problem. Another important source of knowledge can be found &lt;a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=346119&amp;amp;SiteID=1"&gt;here&lt;/a&gt; in
the MSDN forums, where Chris Webb, Thomas Pagel&amp;nbsp;and others discussed it. Now,
I would like to add my solution. Take it or leave it - your choice.
&lt;/p&gt;
&lt;p&gt;
First of all, create a column in the time dimension that will be the current day indicator.
Thanks to the Data Source View or the UDM approach of SSAS 2005 you don't have to
change the relational table itself. Just add a named calculation in the DSV with expression
that will be 1 for the row of the current day and null or zero for the others. The
expression syntax itself depends on the underlying DB so I won't write it here, but
it's very simple.&amp;nbsp;Add this column as an attribute (let's call it CurrentDayInd)&amp;nbsp;in
the dimension structure and select its AttributeVisible propertiey to false. That's
because we don't need such Attribute Hierarchy in our time dimension. After that,
create a new User Hierarchy (you can call it Current Day), where the&amp;nbsp;first level&amp;nbsp;in
it will be CurrentDayInd and after it place the day (key)&amp;nbsp;attribute.
&lt;/p&gt;
&lt;p&gt;
Now, what we have here? We have a hierarchy (Current Day) with two members - 1 and
zero. The 1 member has only one child which is the current day. Link that member to
your regular hierarchy (it's called YSQMD at my place) and here you have it. For example,
you can use it that way in the MDX script:
&lt;/p&gt;
&lt;p&gt;
Create Set [Last 30 Days] as&lt;br&gt;
LinkMember([Time].[Current Day].[CurrentDayInd].&amp;amp;[1].Children.Item(0),[Time].[YSQMD])&lt;br&gt;
:&lt;br&gt;
LinkMember([Time].[Current Day].[CurrentDayInd].&amp;amp;[1].Children.Item(0),[Time].[YSQMD]).Lag(30);
&lt;/p&gt;
&lt;p&gt;
I think that this solution is good and elegant. First of all, you don't have to use
external functions such as Now(). The second pro is that we use the native OLAP mechanism
which saves time and makes the queries run faster. Believe me, you'll feel the difference
with big cubes. The last thing is that this solution is easy to understand (at least
I think so) and it is easy for maintenance. The big con is that you have to process
this dimension (and related cubes) every day. I don't think that it's so bad because
most of the organizations do make process every day.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=2efa7c5b-826e-43c4-af42-5608fdd6c188" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,2efa7c5b-826e-43c4-af42-5608fdd6c188.aspx</comments>
      <category>BI;BI/DataWarehousing;BI/MDX;BI/SQL Server 2005;BI/SQL Server 2005/Analysis Services;BI/SQL Server 2008;BI/SQL Server 2008/Analysis Services</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=dc7a85be-591a-42b6-83c9-4d6c5ef2d8ea</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,dc7a85be-591a-42b6-83c9-4d6c5ef2d8ea.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,dc7a85be-591a-42b6-83c9-4d6c5ef2d8ea.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=dc7a85be-591a-42b6-83c9-4d6c5ef2d8ea</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
This is the second bug I found when working with AS and Oracle as my database (you
can read about the first one <a href="http://www.miky-schreiber.com/Blog/PermaLink,guid,e36d9c69-b16d-4d4b-bea9-05e3a5d02729.aspx">here</a>).
Some background about our Datawarehouse architecture before I begin to complain about
Microsoft:
</p>
        <p>
We cannot afford risking that our users will experience faults or crashes while
we refresh our DWH, process our cubes, etc. What we do to solve this problem is called
a switch: We have two schemas in our Oracle DB. While our users watch the first schema,
we update the other one. Only after we finish all our load process, we switch our
user's tools to see the data from the second schema. In order to implement this architecture
we use Oracle's synonyms. Let's say that the users watch the fact table "sales". We
have a synonym which is called sales_syn. While it's pointing to the first schema
(schema_a.sales_fact), we're loading into the second schema (schema_b.sales_fact).
After that, we switch the synonym so it will point to the second schema (schema_b).
The users always look on views that rely on synonyms. The views never change, only
the synonyms do.
</p>
        <p>
The problem starts when we make Named Queries in our Data Source Views in AS. Apparently,
AS looks inside the view that we enterd into the DSV, finds the target of the
synonym and saves it. Even after we make the switch (the synonym points on the other
schema), the named query will be pointing on the first one. All our efforts
to edit the named query have failed. When we open it again, we will always find that
the first schema is "burned" there and cannot be changed.
</p>
        <p>
The solution we chose is simply avoid using named queries. If we need a simple calculation
we can add a Named Calculation in the Data Source View and if we need a complex view
over our fact table, we write it ourself in the DB. This solutions breaks a little
bit the main point of the data source view (designated place for all the logic of
the DWH), but it is the best solution we could think of right now.
</p>
        <p>
Dear Microsoft developers - it seems that you tried to be smart and look into our
Oracle objects in order to enhance the multidimensional database's performance.
Next time, please think twice before you do.
</p>
        <img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=dc7a85be-591a-42b6-83c9-4d6c5ef2d8ea" />
      </body>
      <title>Analysis Services Named Queries and Oracle's synonyms serious bug</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,dc7a85be-591a-42b6-83c9-4d6c5ef2d8ea.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,dc7a85be-591a-42b6-83c9-4d6c5ef2d8ea.aspx</link>
      <pubDate>Mon, 29 Oct 2007 18:24:36 GMT</pubDate>
      <description>&lt;p&gt;
This is the second bug I found when working with AS and Oracle as my database (you
can read about the first one &lt;a href="http://www.miky-schreiber.com/Blog/PermaLink,guid,e36d9c69-b16d-4d4b-bea9-05e3a5d02729.aspx"&gt;here&lt;/a&gt;).
Some background about our Datawarehouse architecture before I begin to complain about
Microsoft:
&lt;/p&gt;
&lt;p&gt;
We cannot afford risking that our&amp;nbsp;users will experience faults or crashes&amp;nbsp;while
we refresh our DWH, process our cubes, etc. What we do to solve this problem is called
a switch: We have two schemas in our Oracle DB. While our users watch the first schema,
we update the other one. Only after we finish all our load process, we switch our
user's tools to see the data from the second schema. In order to implement this architecture
we use Oracle's synonyms. Let's say that the users watch the fact table "sales". We
have a synonym which is called sales_syn. While it's pointing to the first schema
(schema_a.sales_fact), we're loading into the second schema (schema_b.sales_fact).
After that, we switch the synonym so it will point to the second schema (schema_b).
The users always look on views that rely on synonyms. The views never change, only
the synonyms do.
&lt;/p&gt;
&lt;p&gt;
The problem starts when we make Named Queries in our Data Source Views in AS. Apparently,
AS looks inside the view that&amp;nbsp;we enterd into the DSV, finds the target of the
synonym and saves it. Even after we make the switch (the synonym points on the other
schema), the named query will&amp;nbsp;be pointing&amp;nbsp;on the first one. All our efforts
to edit the named query have failed. When we open it again, we will always find that
the first schema is "burned" there and cannot be changed.
&lt;/p&gt;
&lt;p&gt;
The solution we chose is simply avoid using named queries. If we need a simple calculation
we can add a Named Calculation in the Data Source View and if we need a complex view
over our fact table, we write it ourself in the DB. This solutions breaks a little
bit the main point of the data source view (designated place for all the logic of
the DWH), but it is the best solution we could think of right now.
&lt;/p&gt;
&lt;p&gt;
Dear Microsoft developers - it seems that you tried to be smart and look into our
Oracle objects in order to enhance the&amp;nbsp;multidimensional database's&amp;nbsp;performance.
Next time, please think twice before you do.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=dc7a85be-591a-42b6-83c9-4d6c5ef2d8ea" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,dc7a85be-591a-42b6-83c9-4d6c5ef2d8ea.aspx</comments>
      <category>BI;BI/DataWarehousing;BI/SQL Server 2005;BI/SQL Server 2005/Analysis Services</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=59198e45-39e2-41be-bcee-11a03dbe5d44</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,59198e45-39e2-41be-bcee-11a03dbe5d44.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,59198e45-39e2-41be-bcee-11a03dbe5d44.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=59198e45-39e2-41be-bcee-11a03dbe5d44</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">I believe that every BI developer seen
this in many Data Warehouses: Boolean Dimensions. As you may guess, boolean dimension
is a dimension with only two members and of course with no hierarchy. For example:
cash/credit card in sales cube, exists/not exists in inventory cube, etc. If you haven't
seen this phrase before - relax - I just invented it. :-)<br />
Now, the question is what to do about these dimensions:<br />
a. Include them in the ETL process or just leave it as is?<br />
b. If you put it in the ETL - how would you implement it?<br /><br />
Here's what I did in my project. You may disagree with me and I would like to see
other approaches too.<br />
a. Yes, I included it for some reasons. As every <a href="http://www.pragprog.com/">Pragmatic
Programmer</a> knows, everything can be changed so do not assume anything as globally-static.
This rule takes place in here: Boolean dimensions may grow and have more members.
For example, in the sales cube I mentioned above, maybe there will be another way
to pay such as exclusive card of the shop (There is a network here in Israel who has
it). Even male/female boolean dimension may have an Unknown member. So never exclude
these dimensions from your ETL process. Wait - one more thing. You may think: Why
interrupt my ETL process with these silly dimensions? If they'll grow up I'll add
them to the process. As an answer think about the timings: You can never know how
much time the dimension's ETL will take (although it will be very small), so in order
to stay away of surprises - include it in your ETL process. just for case.<br />
b. I implemented it as two hard-coded expressions and sent them to union. The result
of this union will enter directly to the target table. In Informatica, the mapplet
can't start without source table so just put a dummy table with only one row and connect
it to the expression items. Why only one row? If the table will contain more than
two rows then the Informatica server will consider the process as failed one.<br /><br />
As I said, I'll be happy to read other approaches other than mine.<br /><p></p><img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=59198e45-39e2-41be-bcee-11a03dbe5d44" /></body>
      <title>Boolean Dimensions</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,59198e45-39e2-41be-bcee-11a03dbe5d44.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,59198e45-39e2-41be-bcee-11a03dbe5d44.aspx</link>
      <pubDate>Sun, 21 Oct 2007 22:44:45 GMT</pubDate>
      <description>I believe that every BI developer seen this in many Data Warehouses: Boolean Dimensions. As you may guess, boolean dimension is a dimension with only two members and of course with no hierarchy. For example: cash/credit card in sales cube, exists/not exists in inventory cube, etc. If you haven't seen this phrase before - relax - I just invented it. :-)&lt;br&gt;
Now, the question is what to do about these dimensions:&lt;br&gt;
a. Include them in the ETL process or just leave it as is?&lt;br&gt;
b. If you put it in the ETL - how would you implement it?&lt;br&gt;
&lt;br&gt;
Here's what I did in my project. You may disagree with me and I would like to see
other approaches too.&lt;br&gt;
a. Yes, I included it for some reasons. As every &lt;a href="http://www.pragprog.com/"&gt;Pragmatic
Programmer&lt;/a&gt; knows, everything can be changed so do not assume anything as globally-static.
This rule takes place in here: Boolean dimensions may grow and have more members.
For example, in the sales cube I mentioned above, maybe there will be another way
to pay such as exclusive card of the shop (There is a network here in Israel who has
it). Even male/female boolean dimension may have an Unknown member. So never exclude
these dimensions from your ETL process. Wait - one more thing. You may think: Why
interrupt my ETL process with these silly dimensions? If they'll grow up I'll add
them to the process. As an answer think about the timings: You can never know how
much time the dimension's ETL will take (although it will be very small), so in order
to stay away of surprises - include it in your ETL process. just for case.&lt;br&gt;
b. I implemented it as two hard-coded expressions and sent them to union. The result
of this union will enter directly to the target table. In Informatica, the mapplet
can't start without source table so just put a dummy table with only one row and connect
it to the expression items. Why only one row? If the table will contain more than
two rows then the Informatica server will consider the process as failed one.&lt;br&gt;
&lt;br&gt;
As I said, I'll be happy to read other approaches other than mine.&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=59198e45-39e2-41be-bcee-11a03dbe5d44" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,59198e45-39e2-41be-bcee-11a03dbe5d44.aspx</comments>
      <category>BI;BI/DataWarehousing;BI/Informatica</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=73f9d050-05bd-4dc9-b719-ae9d256557b3</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,73f9d050-05bd-4dc9-b719-ae9d256557b3.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,73f9d050-05bd-4dc9-b719-ae9d256557b3.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=73f9d050-05bd-4dc9-b719-ae9d256557b3</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">I really think that the time dimension
is the most complex dimension in 90% of the DWHs. The complexity is in two places:
In the DWH design and also in Analysis Services (or any other BI tool).<br />
First of all - why we didn't take the already-made Server Time Dimension which exists
in SSAS 2005? For two reasons: The first is that the <a href="http://www.miky-schreiber.com/blog/default.aspx#aa68059bf-fe59-48d5-a9e8-dd366e6a861c">Project
Real</a> guys do not recommend using it (you can find their SSAS article <a href="http://www.microsoft.com/technet/prodtechnol/sql/2005/realastd.mspx">here</a>).
The second is that we wanted to have some features that are not available in the server
time dimension, such as Hebrew date. In a matter of fact, even if we didn't have such
feature we still would build the time dimension ourselves because it's giving you
much more control over the dimension. For example, you can always add some new attributes
which Microsoft developers didn't think about.<br />
I started myself to build the time dimension in excel. I figured out that this mission
is little more complex that I thought it would. Most of the functions I wrote were
simple, but there were some complicated ones. So here are some tips for you if you
want to build your time dimension using Excel:<br /><ul><li>
If you want to week number for every date, do not write the function yourself... Excel
has function called weeknum. If you don't have it just add the function toolbox which
has it (I can't recall its name right now. check in excel help).</li><li>
If you want to have records for every level in your hierarchy (not only for days),
put every level in its own excel file (not excel tab). It will help you later when
you will transfer it to your DB.</li><li>
Check yourself. Pick randomly some dates and check that all of its record has correct
data.</li></ul>
After building the excel files I needed to transfer it to my Oracle server. I used
SSIS because I didn't want to wait for my DBA to copy these files into the Informatica
server (it can't use my the local files, it has to be in its server. SSIS can use
local files). This also was a little tricky. First of all, close excel when running
the SSIS packages, otherwise it will fail. Second, when moving the non-leaf levels,
go into the columns section in the destination box and erase the irrelevant columns.
It will reduce the chance for errors. Finally, click on the source box and click on
"Show advanced editor". Enter the source's output columns options and define properly
the columns' data types. This also will reduce the chance for errors.<br /><br />
I had a little bit of an argument with my DBA about how should the time dimension
be. I think that the time dimension does not have to be processes at all. My time
dimension is from 1960 until 2020, so no daily ETL is required. She says that all
the logic has to be in Informatica so I need to develop a mapping for this dimension.
I think that we both are right and that's because that in ideal world she is right.
In every developers team, all the BL has to be in one place. But we don't have much
time (the deadline is very close) so I won't spend the time building more mapping
in Informatica when I have the time dimension already made in excel.<br /><br />
Maybe someday I will have the time to do this. Maybe not.<br /><p></p><img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=73f9d050-05bd-4dc9-b719-ae9d256557b3" /></body>
      <title>Building my Time dimension with excel</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,73f9d050-05bd-4dc9-b719-ae9d256557b3.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,73f9d050-05bd-4dc9-b719-ae9d256557b3.aspx</link>
      <pubDate>Sun, 14 Oct 2007 23:18:38 GMT</pubDate>
      <description>I really think that the time dimension is the most complex dimension in 90% of the DWHs. The complexity is in two places: In the DWH design and also in Analysis Services (or any other BI tool).&lt;br&gt;
First of all - why we didn't take the already-made Server Time Dimension which exists
in SSAS 2005? For two reasons: The first is that the &lt;a href="http://www.miky-schreiber.com/blog/default.aspx#aa68059bf-fe59-48d5-a9e8-dd366e6a861c"&gt;Project
Real&lt;/a&gt; guys do not recommend using it (you can find their SSAS article &lt;a href="http://www.microsoft.com/technet/prodtechnol/sql/2005/realastd.mspx"&gt;here&lt;/a&gt;).
The second is that we wanted to have some features that are not available in the server
time dimension, such as Hebrew date. In a matter of fact, even if we didn't have such
feature we still would build the time dimension ourselves because it's giving you
much more control over the dimension. For example, you can always add some new attributes
which Microsoft developers didn't think about.&lt;br&gt;
I started myself to build the time dimension in excel. I figured out that this mission
is little more complex that I thought it would. Most of the functions I wrote were
simple, but there were some complicated ones. So here are some tips for you if you
want to build your time dimension using Excel:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;
If you want to week number for every date, do not write the function yourself... Excel
has function called weeknum. If you don't have it just add the function toolbox which
has it (I can't recall its name right now. check in excel help).&lt;/li&gt;
&lt;li&gt;
If you want to have records for every level in your hierarchy (not only for days),
put every level in its own excel file (not excel tab). It will help you later when
you will transfer it to your DB.&lt;/li&gt;
&lt;li&gt;
Check yourself. Pick randomly some dates and check that all of its record has correct
data.&lt;/li&gt;
&lt;/ul&gt;
After building the excel files I needed to transfer it to my Oracle server. I used
SSIS because I didn't want to wait for my DBA to copy these files into the Informatica
server (it can't use my the local files, it has to be in its server. SSIS can use
local files). This also was a little tricky. First of all, close excel when running
the SSIS packages, otherwise it will fail. Second, when moving the non-leaf levels,
go into the columns section in the destination box and erase the irrelevant columns.
It will reduce the chance for errors. Finally, click on the source box and click on
"Show advanced editor". Enter the source's output columns options and define properly
the columns' data types. This also will reduce the chance for errors.&lt;br&gt;
&lt;br&gt;
I had a little bit of an argument with my DBA about how should the time dimension
be. I think that the time dimension does not have to be processes at all. My time
dimension is from 1960 until 2020, so no daily ETL is required. She says that all
the logic has to be in Informatica so I need to develop a mapping for this dimension.
I think that we both are right and that's because that in ideal world she is right.
In every developers team, all the BL has to be in one place. But we don't have much
time (the deadline is very close) so I won't spend the time building more mapping
in Informatica when I have the time dimension already made in excel.&lt;br&gt;
&lt;br&gt;
Maybe someday I will have the time to do this. Maybe not.&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=73f9d050-05bd-4dc9-b719-ae9d256557b3" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,73f9d050-05bd-4dc9-b719-ae9d256557b3.aspx</comments>
      <category>BI;BI/DataWarehousing;BI/Informatica;BI/SQL Server 2005/Integration Services</category>
    </item>
    <item>
      <trackback:ping>http://www.miky-schreiber.com/Blog/Trackback.aspx?guid=01276594-f240-4611-940c-6626b856977c</trackback:ping>
      <pingback:server>http://www.miky-schreiber.com/Blog/pingback.aspx</pingback:server>
      <pingback:target>http://www.miky-schreiber.com/Blog/PermaLink,guid,01276594-f240-4611-940c-6626b856977c.aspx</pingback:target>
      <dc:creator>mikypuff</dc:creator>
      <wfw:comment>http://www.miky-schreiber.com/Blog/CommentView,guid,01276594-f240-4611-940c-6626b856977c.aspx</wfw:comment>
      <wfw:commentRss>http://www.miky-schreiber.com/Blog/SyndicationService.asmx/GetEntryCommentsRss?guid=01276594-f240-4611-940c-6626b856977c</wfw:commentRss>
      <slash:comments>5</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">I guess that this will not be my last post
on this subject, but I want to start sharing some thoughts and tips from my experience
when designing and building DWH. In this post I will focus on the fact &amp; dimensions
tables relationship in terms of data completeness (if you wonder what it is, read
on).<br /><br />
Before you start to design the DWH, sit and talk with the people who built the systems
which you take your data from, including the DBA. For every table, ask them what is
the primary key (it's NOT always defined properly in the DB), then ask them again
and then ask them if they are sure. It happened to me that I discovered that the systems
guys were wrong about their DB's primary keys.<br />
The same thing is about Foreign keys and here you should be even more careful. Even
if they claim so, check <b>yourself</b> that every foreign key in the fact table is
placed correctly in the dimension table, <b>especially when the fact table has far
history records</b>. Sometimes system developers or even worse - system DBAs delete
records from the dimension tables that are not relevant. This will cause that these
keys will still be in the fact's history records but will not be found in the dimension
table, causing uncomplete relationship between the fact and the dimension table.<br /><br />
So far is about the part when you talk and "investigate" the system developers (the
DWH design). What to do when you actually developing the DWH? First, develop the tables
of your dimensions tables. <b>Do not forget</b> to add the primary keys in the dimensions
tables and the primary and foreign keys in the fact table. Then develop the ETL processes
and go for the dimensions first.  If you know that the dimension has completeness
problems with the fact table that you will develop later (you talked with the system
developers, remember?), add UNDEFINED (UD key) record for the dimension table. Later,
when developing the fact table's ETL process, make Join with the dimension table and
check that the records' foreign key exists there. If not - change the key to UD. In
SSIS and Informatica (and I guess that also in other products I don't know, such as
DataStage) you can use Lookup instead of Joiner if the dimension table is less that
1G records. That will optimize the ETL process. After you developed all your ETLs,
run the dimension processes. After they finish (assuming everything went OK) run the
fact table's ETL process. If it succeeded you can go and have a drink. If not - check
what went wrong. If you want to know which keys didn't showed up in the dimension
table and causes the <span style="font-size: 12pt; line-height: 115%; font-family: &quot;Times New Roman&quot;,&quot;serif&quot;;">incompleteness </span>problem,
you can <b>disable</b> (not delete) the foreign key from the fact table and run the
process again. Then, with a simple SQL query, check which foreign keys don't exist
in the dimension table. Go back to your ETL design and check what you did wrong. As
I pointed before, in this step you might be very angry at the system developers...<br /><br />
That is all for now. As I said, I assume that more ideas will come on in the future.<br /><p></p><img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=01276594-f240-4611-940c-6626b856977c" /></body>
      <title>Tips for use when designing and building your DataWarehouse</title>
      <guid isPermaLink="false">http://www.miky-schreiber.com/Blog/PermaLink,guid,01276594-f240-4611-940c-6626b856977c.aspx</guid>
      <link>http://www.miky-schreiber.com/Blog/PermaLink,guid,01276594-f240-4611-940c-6626b856977c.aspx</link>
      <pubDate>Sat, 13 Oct 2007 22:11:49 GMT</pubDate>
      <description>I guess that this will not be my last post on this subject, but I want to start sharing some thoughts and tips from my experience when designing and building DWH. In this post I will focus on the fact &amp;amp; dimensions tables relationship in terms of data completeness (if you wonder what it is, read on).&lt;br&gt;
&lt;br&gt;
Before you start to design the DWH, sit and talk with the people who built the systems
which you take your data from, including the DBA. For every table, ask them what is
the primary key (it's NOT always defined properly in the DB), then ask them again
and then ask them if they are sure. It happened to me that I discovered that the systems
guys were wrong about their DB's primary keys.&lt;br&gt;
The same thing is about Foreign keys and here you should be even more careful. Even
if they claim so, check &lt;b&gt;yourself&lt;/b&gt; that every foreign key in the fact table is
placed correctly in the dimension table, &lt;b&gt;especially when the fact table has far
history records&lt;/b&gt;. Sometimes system developers or even worse - system DBAs delete
records from the dimension tables that are not relevant. This will cause that these
keys will still be in the fact's history records but will not be found in the dimension
table, causing uncomplete relationship between the fact and the dimension table.&lt;br&gt;
&lt;br&gt;
So far is about the part when you talk and "investigate" the system developers (the
DWH design). What to do when you actually developing the DWH? First, develop the tables
of your dimensions tables. &lt;b&gt;Do not forget&lt;/b&gt; to add the primary keys in the dimensions
tables and the primary and foreign keys in the fact table. Then develop the ETL processes
and go for the dimensions first.&amp;nbsp; If you know that the dimension has completeness
problems with the fact table that you will develop later (you talked with the system
developers, remember?), add UNDEFINED (UD key) record for the dimension table. Later,
when developing the fact table's ETL process, make Join with the dimension table and
check that the records' foreign key exists there. If not - change the key to UD. In
SSIS and Informatica (and I guess that also in other products I don't know, such as
DataStage) you can use Lookup instead of Joiner if the dimension table is less that
1G records. That will optimize the ETL process. After you developed all your ETLs,
run the dimension processes. After they finish (assuming everything went OK) run the
fact table's ETL process. If it succeeded you can go and have a drink. If not - check
what went wrong. If you want to know which keys didn't showed up in the dimension
table and causes the &lt;span style="font-size: 12pt; line-height: 115%; font-family: &amp;quot;Times New Roman&amp;quot;,&amp;quot;serif&amp;quot;;"&gt;incompleteness &lt;/span&gt;problem,
you can &lt;b&gt;disable&lt;/b&gt; (not delete) the foreign key from the fact table and run the
process again. Then, with a simple SQL query, check which foreign keys don't exist
in the dimension table. Go back to your ETL design and check what you did wrong. As
I pointed before, in this step you might be very angry at the system developers...&lt;br&gt;
&lt;br&gt;
That is all for now. As I said, I assume that more ideas will come on in the future.&lt;br&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.miky-schreiber.com/Blog/aggbug.ashx?id=01276594-f240-4611-940c-6626b856977c" /&gt;</description>
      <comments>http://www.miky-schreiber.com/Blog/CommentView,guid,01276594-f240-4611-940c-6626b856977c.aspx</comments>
      <category>BI;BI/DataWarehousing;BI/Informatica;BI/SQL Server 2005/Integration Services</category>
    </item>
  </channel>
</rss>