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

<channel>
	<title>Rittman Mead Consulting</title>
	<atom:link href="http://www.rittmanmead.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.rittmanmead.com</link>
	<description>Delivered Intelligence</description>
	<lastBuildDate>Mon, 08 Feb 2010 21:55:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Data Warehouse Fault Tolerance Part 1: Resuming</title>
		<link>http://www.rittmanmead.com/2010/02/08/data-warehouse-fault-tolerance-part-1-resuming/</link>
		<comments>http://www.rittmanmead.com/2010/02/08/data-warehouse-fault-tolerance-part-1-resuming/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 14:41:45 +0000</pubDate>
		<dc:creator>Stewart Bryson</dc:creator>
				<category><![CDATA[Data Warehousing]]></category>
		<category><![CDATA[Oracle Database]]></category>

		<guid isPermaLink="false">http://www.rittmanmead.com/?p=4314</guid>
		<description><![CDATA[In the introduction to this series of posts, I spoke briefly about data warehouse fault tolerance and the unique challenges resulting from high data volumes combined the batch load window required to create them. I then defined the goal: a layered approach allowing simple errors to be caught early before they turn in to serious [...]]]></description>
			<content:encoded><![CDATA[<p>In the <a href="http://www.rittmanmead.com/2010/02/02/data-warehouse-fault-tolerance-an-introduction/">introduction</a> to this series of posts, I spoke briefly about data warehouse fault tolerance and the unique challenges resulting from high data volumes combined the batch load window required to create them. I then defined the goal: a layered approach allowing simple errors to be caught early before they turn in to serious conditions.</p>
<p>Resuming is the ability to continue effortlessly after an error. The important thing is that there should be no aftermath from the error: our process should pause gracefully until the error is corrected. The Oracle Database has offered out of the box functionality for resuming since version 9i in the form of Resumable Space Allocation. Resumable operations are supported for SELECT queries, DML and DDL, and can be enabled at either the system or the session level. To enable at the system level, the RESUMABLE_TIMEOUT database parameter should have a non-zero value.</p>
<pre>SQL&gt; alter system set resumable_timeout=3600;

System altered.

SQL&gt;</pre>
<p>To enable resumable operations at the session level, the statement follows this basic syntax, with the TIMEOUT and NAME clauses being optional:</p>
<p>ALTER SESSION ENABLE RESUMABLE &lt;TIMEOUT <em>n</em>&gt; &lt;NAME <em>string</em>&gt;;</p>
<p>The TIMEOUT value is specified in seconds, and if omitted, the default value of 7200 is used, or 2 hours. The NAME clause gives the resumable session a user-friendly name for when we are monitoring for resumable sessions (as we will see later) to see which of our processes is suspended. Enabling resumable operations for the session level requires that the RESUMABLE permission has been granted:</p>
<pre>SQL&gt; grant resumable to stewart;

Grant succeeded.

SQL&gt;</pre>
<p>Resumable operations can also be enabled with the Oracle utilities&#8230; such as SQL-Loader, Export/Import and Datapump. The command-line parameters RESUMABLE, RESUMABLE_NAME and RESUMABLE_TIMEOUT exist to mimic the functionality mentioned above.</p>
<p>Now for a demonstration. I&#8217;ll create a situation that is ripe for a space allocation error: I&#8217;ll put an empty copy of the SALES fact table from the SH schema in a tablespace with only 250K of space:</p>
<pre>SQL&gt; create tablespace target datafile '/oracle/oradata/bidw1/target01.dbf' size 250K;

Tablespace created.

SQL&gt; create table target.sales tablespace target as select * from sh.sales where 1=0;

Table created.

SQL&gt;</pre>
<p>Now I&#8217;ll load some records into the table, which should cause it to suspend. To prepare my session, I need to enable resumable operations. Since I always instrument my code, I&#8217;ll register my process with the database. After that, I have an easy way to guarantee consistency when referring to processes. Now, I can use the registered name for my resumable session as well:</p>
<pre>SQL&gt; exec dbms_application_info.set_module('SALES fact load','insert some rows');

PL/SQL procedure successfully completed.

SQL&gt;
SQL&gt; DECLARE
  2     l_module VARCHAR2(48) := sys_context('USERENV','MODULE');
  3  BEGIN
  4     EXECUTE IMMEDIATE
  5     'alter session enable resumable timeout 18000 name '''||l_module||'''';
  6  END;
  7  /

PL/SQL procedure successfully completed.

SQL&gt;</pre>
<p>I start loading the records in hopes of a suspended session:</p>
<pre>SQL&gt; insert into target.sales select * from sh.sales;</pre>
<p>So now, I open up another session, and I start another transaction against the TARGET.SALES table, just to pile on the TARGET tablespace:</p>
<pre>SQL&gt; exec dbms_application_info.set_module('SALES fact load2','insert more rows');

PL/SQL procedure successfully completed.

SQL&gt;
SQL&gt; DECLARE
  2     l_module VARCHAR2(48) := sys_context('USERENV','MODULE');
  3  BEGIN
  4     EXECUTE IMMEDIATE
  5     'alter session enable resumable timeout 18000 name '''||l_module||'''';
  6  END;
  7  /

PL/SQL procedure successfully completed.

SQL&gt; insert into target.sales select * from sh.sales;</pre>
<p>I&#8217;ll have a look in the DBA_RESUMABLE view (there is also a USER_RESUMABLE version) for my suspended sessions. Even though I could get all the following information with a single SQL statement, I broke it up for better visibility on the blog:</p>
<pre>SQL&gt; select name, start_time, suspend_time, status from dba_resumable;

NAME              | START_TIME           | SUSPEND_TIME         | STATUS
----------------- | -------------------- | -------------------- | ------------
SALES fact load2  | 02/06/10 10:33:33    | 02/06/10 10:33:33    | SUSPENDED
SALES fact load   | 02/06/10 10:29:03    | 02/06/10 10:29:03    | SUSPENDED

2 rows selected.

Elapsed: 00:00:00.07
SQL&gt; select name, sql_text from dba_resumable;

NAME              | SQL_TEXT
----------------- | -----------------------------------------------
SALES fact load2  | insert into target.sales select * from sh.sales
SALES fact load   | insert into target.sales select * from sh.sales

2 rows selected.

SQL&gt; select name, error_msg from dba_resumable;

NAME              | ERROR_MSG
----------------- | ------------------------------------------------------------------------
SALES fact load2  | ORA-01653: unable to extend table TARGET.SALES by 8 in tablespace TARGET
SALES fact load   | ORA-01653: unable to extend table TARGET.SALES by 8 in tablespace TARGET

2 rows selected.

SQL&gt;</pre>
<p>The Oracle Database also publishes server alerts concerning suspended transactions using the Server-Generated Alerts infrastructure. This infrastructure uses the AWR toolset, the server package DBMS_SERVER_ALERT for getting and setting metric threshholds, and the queue table ALERT_QUE to hold alerts that have been published from AWR. Custom processes could be written to mine ALERT_QUE for these alerts, but the easiest way to configure and view server alerts is using Oracle Enterprise Manager (OEM). On the Alerts section of the main OEM page, we can see three different alerts generated by the Oracle Database:</p>
<div style="text-align:center"><a href="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/all-alerts.png"><img class="aligncenter" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/all-alerts.png" border="0" alt="all alerts.png" width="500" height="228" /></a></div>
<p>If we click on the &#8220;Session Suspended&#8221; link, we can see the multiple alerts generated in this category:</p>
<div style="text-align:center"><a href="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/suspend-alerts.png"><img class="aligncenter" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/suspend-alerts.png" border="0" alt="suspend alerts.png" width="500" height="81" /></a></div>
<p>Another alert generated indirectly by the suspended transaction is the &#8220;Configuration&#8221; class event caused by our session &#8220;waiting&#8221; to proceed. The Oracle wait event interface can show us information about the suspend waits on the system:</p>
<pre>SQL&gt; SELECT event,
  2         SUM(time_waited) time_waited,
  3         SUM(total_waits) total_waits,
  4         AVG(average_wait) average_wait
  5    FROM gv$session_event
  6   WHERE lower(event) LIKE '%suspend%'
  7   GROUP BY event
  8   ORDER BY time_waited ASC
  9  /

EVENT                                          | TIME_WAITED | TOTAL_WAITS | AVERAGE_WAIT
---------------------------------------------- | ----------- | ----------- | ------------
statement suspended, wait error to be cleared  |      305373 |        1377 |       221.78

1 row selected.

SQL&gt;</pre>
<p>To free up the space issue, I&#8217;ll enable autoextend on the TARGET tablespace. Then, I&#8217;ll take a look and see if anything has changed:</p>
<pre>SQL&gt; alter database datafile '/oracle/oradata/bidw1/target01.dbf'
  2  autoextend on next 10M maxsize 1000M;

Database altered.

SQL&gt; select status, resume_time, name from dba_resumable;

STATUS       | RESUME_TIME          | NAME
------------ | -------------------- | -----------------
NORMAL       | 02/06/10 10:56:49    | SALES fact load2
NORMAL       | 02/06/10 10:56:49    | SALES fact load

2 rows selected.

SQL&gt;</pre>
<p>The Resumable Space Allocation features includes the AFTER SUSPEND trigger, which allows the specification of a system-wide trigger that will fire whenever a transaction is suspended. The typical use for this functionality is alerting as suspended operations don&#8217;t write anything to the alert log.</p>
<p><strong>UPDATE: I made a mistake here&#8230; suspended transactions do in fact cause entries in the alert log, and so does the RESUME process detailed below.</strong></p>
<p>There are some features in the DBMS_RESUMABLE package that may make sense when writing an AFTER SUSPEND trigger:</p>
<pre>SQL&gt; desc dbms_resumable
PROCEDURE ABORT
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SESSIONID                      NUMBER                  IN
FUNCTION GET_SESSION_TIMEOUT RETURNS NUMBER
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SESSIONID                      NUMBER                  IN
FUNCTION GET_TIMEOUT RETURNS NUMBER
PROCEDURE SET_SESSION_TIMEOUT
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 SESSIONID                      NUMBER                  IN
 TIMEOUT                        NUMBER                  IN
PROCEDURE SET_TIMEOUT
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 TIMEOUT                        NUMBER                  IN
FUNCTION SPACE_ERROR_INFO RETURNS BOOLEAN
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 ERROR_TYPE                     VARCHAR2                OUT
 OBJECT_TYPE                    VARCHAR2                OUT
 OBJECT_OWNER                   VARCHAR2                OUT
 TABLE_SPACE_NAME               VARCHAR2                OUT
 OBJECT_NAME                    VARCHAR2                OUT
 SUB_OBJECT_NAME                VARCHAR2                OUT

SQL&gt;</pre>
<p>This package adds functionality for writing custom processes in the AFTER SUSPEND trigger. The SPACE_ERROR_INFO function returns specifics about the table and tablespace affected by the space error. A series of checks could be coded enabling specific actions depending on which objects were affected. A suspended process can be ended prematurely with the ABORT procedure, or more time can be added using the SET_TIMEOUT procedure. I actually had one client explain how she had written an AFTER SUSPEND trigger that compiled information about the tablespace affected so that an &#8220;ALTER DATABASE&#8230; RESIZE&#8230;&#8221; command could be issued to add more space to the affected datafile. I didn&#8217;t have the heart to tell her that she had basically written a feature that already existed in the database: AUTOEXTEND.</p>
<p>So what are the best practices to take away from this? Quite simply&#8230; all ETL mappings and flows, as well as database maintenance processes, should use Resumable Space Allocation, preferably using the NAME clause in conjunction with DBMS_APPLICATION_INFO. Setting a RESUMABLE_TIMEOUT value at the system level can be scary, because a single suspended transaction could cause locks that reverberate all the way through the system. But is this really a concern in a BI/DW environment? Are there any processes in our batch load window or with any of our operational maintenance processes that we wouldn&#8217;t want to enable for resumable operations, no matter how many processes back up waiting for them to complete? It could spell bad news if we used any kind of synchronous replication technology to move data to the DW instance, but short of that, I can&#8217;t think of any. Please let me know if you have alternative viewpoints.</p>
<p>I&#8217;ve never found much reason to use the AFTER SUSPEND trigger though. Data warehouses should have production-type monitoring running already, just like other production systems. OEM is more than satisfactory for basic monitoring and alerting, and with the Server-Generated Alerts introduced in 10g, forms a complete product for Oracle environments. But regardless of which monitoring solution is used, it should be able to issue simple queries against the database and alert based on the results of those queries. A select against the DBA_RESUMABLE table provides all the information required to send out an alert, and with features such as AUTOEXTEND, I just can&#8217;t see a requirement for the ability to issue procedural code because a transaction is suspended.</p>
<p><strong>UPDATE: as pointed out above, since suspended transactions do in fact show up in the alert log, this is good news for integrating Resumable Space Allocation into an existing environment. Assuming that there&#8217;s proper alert log monitoring with paging functionality already in place, implementing resumable operations can simply use that infrastructure already in place.</strong></p>
<p>Keep your eyes open for the next of the &#8220;Three R&#8217;s&#8221; in BI/DW fault tolerance: Restarting.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rittmanmead.com/2010/02/08/data-warehouse-fault-tolerance-part-1-resuming/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Oracle BI EE 10.1.3.4.1 &#8211; Modeling Measure Dimensions on Relational Sources &#8211; Essbase Style</title>
		<link>http://www.rittmanmead.com/2010/02/03/oracle-bi-ee-10-1-3-4-1-modeling-measure-dimensions-on-relational-sources-essbase-style/</link>
		<comments>http://www.rittmanmead.com/2010/02/03/oracle-bi-ee-10-1-3-4-1-modeling-measure-dimensions-on-relational-sources-essbase-style/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 19:04:22 +0000</pubDate>
		<dc:creator>Venkatakrishnan J</dc:creator>
				<category><![CDATA[Dimensional Modelling]]></category>
		<category><![CDATA[Hyperion Essbase]]></category>
		<category><![CDATA[Oracle BI Suite EE]]></category>

		<guid isPermaLink="false">http://www.rittmanmead.com/?p=4287</guid>
		<description><![CDATA[One of the biggest differences between Essbase and most other reporting/OLAP tools like BI EE/Oracle OLAP etc is in the way Measures are treated(comparison only in terms of data modeling and reporting and not on physical implementation). In Essbase, every data/value(cell) is attributed by a set of dimensions. Even a measure is considered as an [...]]]></description>
			<content:encoded><![CDATA[<p>One of the biggest differences between Essbase and most other reporting/OLAP tools like BI EE/Oracle OLAP etc is in the way Measures are treated(comparison only in terms of data modeling and reporting and not on physical implementation). In Essbase, every data/value(cell) is attributed by a set of dimensions. Even a measure is considered as an attribute of another dimension. But in the case of Oracle OLAP, BI EE etc, one requires to specifically identify a set of measures and load/report against them. The problem with this approach is the fact that in many cases while doing the reporting we would like to treat the measures like a normal dimension and vice versa. Just to illustrate this point, the most commonly used component in BI EE Answers is the Pivot View component. A Pivot View basically converts a set of dimension attributes as a set of measures(typical analysis) by spreading all the dimension attributes in the column section.</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image.png" border="0" alt="image" width="504" height="99" /></p>
<p>Similarly, in many cases, we want to treat the measures as a set of dimension attributes as shown below</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image1.png" border="0" alt="image" width="403" height="177" /></p>
<p>Again pivot table component can be used to achieve this. Both SQL and MDX can swap the attributes to Columns and Rows pretty efficiently(basically one can manually handcraft SUM, FIRST etc kind of aggregation on any valid column). But once we designate a set of static measures within the reporting tool, the model can become constrained to an extent. Of course, there are ways around it like using Pivot tables, Answers based aggregation, UNIONs etc. The main drawback with a measure based model is the fact that one cannot efficiently drill on Measure Hierarchies. The other drawback is since our database related data structures are more oriented towards static measure modeling (facts and dimensions), it is very difficult to switch the measure hierarchy for reporting.</p>
<p>For example, if you had gone through or attended our training days event last year, we had shown how to go about switching measure hierarchies in BI EE for an Essbase source. Its a very common requirement when you have Essbase as a data source. Many users might choose Accounts dimension as a measure dimension for reporting. Some users might choose Scenario as the measure dimension for reporting. Essbase provides that flexibility and the same can be leveraged from BI EE as well. But in the case of relational sources, it can be quite difficult to achieve this. There are a couple of reasons for this</p>
<p>1. If we model a separate measure dimension in our warehouse, the fact tables will contain only one measure. The size of the fact table will grow multiplied by the number of measures in the measure dimension.</p>
<p>2. Its not practical(&amp; to an extent does not make sense) to model it this way for relational data models at the database level.</p>
<p>Though we might stick with a fact/dimensional model in the data warehouse, i think the reporting tools should provide the capability to switch the measure dimensions even for relational sources(PIVOT and UNPIVOT operations should be supported from the RPD). Currently we do not have this capability in BI EE (from a repository standpoint). Though BI EE does not support this currently, the BI Server repository can be tweaked to an extent to achieve this using Conforming Dimensions. Lets look at a couple of scenarios. One is modeling the measure dimension for relational sources and the other is in switching the measure dimension itself.</p>
<p><strong>Measure Dimension:</strong></p>
<p>Lets understand this through our usual example SH schema that gets shipped with oracle database. Most common way of designing a repository for this SH schema is given below</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image2.png" border="0" alt="image" width="165" height="315" /></p>
<p>Its a very simple repository containing a Sales measure, a cost measure and all the dimensions. If you look at this, UNIT_COST and AMOUNT_SOLD are designated as measures(which is how it exists in the physical database). Lets assume that a requirement is to treat both these measures as attributes of a measure column i.e we want to be in a position to treat both the measures as part of a single dimension. The report below basically explains what is needed</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image3.png" border="0" alt="image" width="234" height="143" /></p>
<p>The above report has a column called Measure which will basically un-pivot the measure values. To achieve this, we start with creating a new custom dimension within the RPD called as Measure Dim. This will basically have one column called as Measure which will be fed through 2 logical table sources (one is Sales and the other is Costs). This is to signify that each LTS will be used to serve each measure</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image4.png" border="0" alt="image" width="160" height="83" /></p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image5.png" border="0" alt="image" width="504" height="163" /></p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image6.png" border="0" alt="image" width="504" height="153" /></p>
<p>Then we create 2 custom fact tables (one for sales measure and the other for cost measure) and then force the conforming dimension join as shown below</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image7.png" border="0" alt="image" width="192" height="265" /></p>
<p>To combine both the measures through a common single fact, we create another logical fact table with one logical column. This will be fed through a logical calculation of UNIT_COST and AMOUNT_SOLD as shown below</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image8.png" border="0" alt="image" width="168" height="276" /></p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image9.png" border="0" alt="image" width="411" height="265" /></p>
<p>This will provide an extra dimension for your reporting (measure dimension). Remember, this will work as long as you have measures from different physical tables. If you have measures from the same physical table then you will have to alias the table as many times as the number of measures (which is not recommended). Also, currently we cannot make BI EE to push the PIVOT and UNPIVOT operators directly from the BMM.</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image3.png" border="0" alt="image" width="234" height="143" /></p>
<p><strong>Swapping Measure Dimensions:</strong></p>
<p>The next requirement is, now that we have converted the measures as a set of attributes derived from a column, to convert each member of the CHANNEL_CLASS column as a measure i.e we want 3 measures <strong>Direct</strong>, <strong>Indirect</strong> and <strong>Others</strong>. To do this, replicate the measure in each fact table 3 times. Basically each measure will have a FILTER function applied to filter only on the necessary attributes. For example, the Sales and Cost fact tables are shown below</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image10.png" border="0" alt="image" width="125" height="315" /></p>
<p>The Direct measure will have a FILTER function applied as shown below</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image11.png" border="0" alt="image" width="409" height="266" /></p>
<p>Similar filters will be applied for Indirect and Others measures as well for both the fact tables. Then in the main fact table, we need to combine the individual measures again.</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image12.png" border="0" alt="image" width="407" height="260" /></p>
<p>This will allow you to create a report containing the actual measures as Dimension attributes and the actual dimension attributes as measures (all of this in a normal table view)</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="image" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/image13.png" border="0" alt="image" width="387" height="162" /></p>
<p>If you look at the SQL, you will notice that there will be conforming dimension join done on the Amount Sold and Unit Price attributes and then they are combined using a main query</p>
<pre>WITH
SAWITH0 AS (select sum(case  when T1776.CHANNEL_CLASS = 'Direct' then T1929.AMOUNT_SOLD end ) as c1,
     sum(case  when T1776.CHANNEL_CLASS = 'Indirect' then T1929.AMOUNT_SOLD end ) as c2,
     sum(case  when T1776.CHANNEL_CLASS = 'Others' then T1929.AMOUNT_SOLD end ) as c3,
     'Amount Sold' as c4,
     T1916.PROMO_NAME as c5
from
     PROMOTIONS T1916,
     CHANNELS T1776,
     SALES T1929
where  ( T1776.CHANNEL_ID = T1929.CHANNEL_ID and T1916.PROMO_ID = T1929.PROMO_ID and (T1776.CHANNEL_CLASS in ('Direct', 'Indirect', 'Others')) )
group by T1916.PROMO_NAME),
SAWITH1 AS (select sum(case  when T1776.CHANNEL_CLASS = 'Direct' then T1784.UNIT_COST end ) as c1,
     sum(case  when T1776.CHANNEL_CLASS = 'Indirect' then T1784.UNIT_COST end ) as c2,
     sum(case  when T1776.CHANNEL_CLASS = 'Others' then T1784.UNIT_COST end ) as c3,
     'Unit Price' as c4,
     T1916.PROMO_NAME as c5
from
     PROMOTIONS T1916,
     CHANNELS T1776,
     COSTS T1784
where  ( T1776.CHANNEL_ID = T1784.CHANNEL_ID and T1784.PROMO_ID = T1916.PROMO_ID and (T1776.CHANNEL_CLASS in ('Direct', 'Indirect', 'Others')) )
group by T1916.PROMO_NAME)
select distinct case  when SAWITH0.c4 is not null then SAWITH0.c4 when SAWITH1.c4 is not null then SAWITH1.c4 end  as c1,
     case  when SAWITH1.c5 is not null then SAWITH1.c5 when SAWITH0.c5 is not null then SAWITH0.c5 end  as c2,
     nvl(SAWITH1.c1 , 0) + nvl(SAWITH0.c1 , 0) as c3,
     nvl(SAWITH1.c2 , 0) + nvl(SAWITH0.c2 , 0) as c4,
     nvl(SAWITH1.c3 , 0) + nvl(SAWITH0.c3 , 0) as c5
from
     SAWITH0 full outer join SAWITH1 On SAWITH0.c4 = SAWITH1.c4 and SAWITH0.c5 = SAWITH1.c5
order by c1, c2</pre>
<p>Though this will work in most cases, there are some drawbacks with this approach</p>
<p>1. The SQLs generated will not be the best performing ones. As the number of measures grow, the number of conforming dimension joins will increase thereby producing poor performance. Unfortunately BI EE cannot push the PIVOT/UNPIVOT operators supported from Oracle 11g</p>
<p>2. If there are a lot of measures from a single fact table then this requires multiple fact table aliases to force the conforming dimension join across all dimension sources (For the measure dim). This might make the RPD un-necessarily big.</p>
<p>You might not find this technique to be of practical use, but this demonstrates the capabilities of the BI Server to model some complex requirements. I am hoping that sometime in the near future we should see more of pure multi-dimensional modeling on relational sources to be supported by BI EE.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rittmanmead.com/2010/02/03/oracle-bi-ee-10-1-3-4-1-modeling-measure-dimensions-on-relational-sources-essbase-style/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Data Warehouse Fault Tolerance: An Introduction</title>
		<link>http://www.rittmanmead.com/2010/02/02/data-warehouse-fault-tolerance-an-introduction/</link>
		<comments>http://www.rittmanmead.com/2010/02/02/data-warehouse-fault-tolerance-an-introduction/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 17:06:01 +0000</pubDate>
		<dc:creator>Stewart Bryson</dc:creator>
				<category><![CDATA[Data Warehousing]]></category>
		<category><![CDATA[Oracle Database]]></category>

		<guid isPermaLink="false">http://www.rittmanmead.com/?p=4249</guid>
		<description><![CDATA[With so much of the blog devoted to OBIEE, OWB and Essbase lately, I felt like it was time to do a few database-related postings. In the past, when I&#8217;ve posted database content to the blog, I usually gravitate toward ETL-related features: those that waffle between database administration and ETL development. But this time I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>With so much of the blog devoted to OBIEE, OWB and Essbase lately, I felt like it was time to do a few database-related postings. In the past, when I&#8217;ve posted database content to the blog, I usually gravitate toward ETL-related features: those that waffle between database administration and ETL development. But this time I&#8217;m going to take a very different route and discuss data warehouse fault tolerance, and so I&#8217;ll be doing a series of postings that discuss what it means to strive to be fault-free.</p>
<p>Fault tolerance isn&#8217;t disaster recovery exactly&#8230; though there&#8217;s a lot of overlap. Instead, fault tolerance is the ability to recover from errors, and those errors can result from hardware issues, software issues, general systems issues (network latency, out-of-space errors), and human mistakes. The main point is that BI/DW environments present unique challenges, both for operations and for the development team. I&#8217;m not preposing that the divide between transactional and reporting systems is necessarily vast&#8230; we still need redundant storage systems and dependable backup strategies. I am preposing, however, that one-size-fits-all approaches to fault-tolerance is problematic, and applying standards that evolved in support of transactional systems may not provide the best protection for BI/DW environments.</p>
<p>The operational teams (DBAs, Unix Admins, Storage Admins, etc.) and the development teams (source system extraction, ETL) have to work closer in a BI/DW than perhaps they do in OLTP environments. Of course, OLTP developers have to write scalable code&#8230; but I think that&#8217;s within their control for the most part. ETL developers are thrashing around millions or billions of rows of data, and because of this, everything needs to be well-oiled: undo spaces need to be available, temp space needs to be plentiful, standard operational jobs such as backup and recovery or statistics gathering need to keep the batch load window in mind, etc. Whereas OLTP code is exclusively SQL&#8230; ETL code is packed full of DDL: partition-exchange loads, index and constraint maintenance, table truncates, the whole gamut.</p>
<p>So when working with millions or billions of rows, we need to eliminate errors as best we can. Sounds simple enough, but the truth is that errors are going to happen, and there&#8217;s nothing we can do to wipe them out completely. But we can mitigate. So we need to introduce a triage process: catching and correcting errors as early as possible so that their damage is minimal. In essence: don&#8217;t let simple errors turn into weekend-long data correction issues, where millions of rows need to be updated or deleted. Let&#8217;s work smarter, not harder, using every solution available to use, including features present in the Oracle Database, best practices in ETL development, and possible modifications to our backup and recovery strategies.</p>
<p>I should note that, when speaking of BI/DW environments, I still have the batch load paradigm squarely in mind. Although the line in the sand is certainly moving in one constant direction, most data warehouses are still loaded with either batch or mini-batch processing. However, being a fan of near-real-time data warehouse techniques (as my colleague Peter Scott has written from time to time&#8230; only reporting from the source system itself is truly real-time), I&#8217;ll be sure to point out how some of these techniques differ the closer we get to the actual transaction.</p>
<p>I currently have three postings in mind that correlate to the Three R&#8217;s of Data Warehouse Fault Tolerance. Be on the lookout for the first installment coming soon: Resuming.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rittmanmead.com/2010/02/02/data-warehouse-fault-tolerance-an-introduction/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fantasy Football &#8211; When is a fact not a Fact?</title>
		<link>http://www.rittmanmead.com/2010/02/02/fantasy-football-when-is-a-fact-not-a-fact/</link>
		<comments>http://www.rittmanmead.com/2010/02/02/fantasy-football-when-is-a-fact-not-a-fact/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 00:13:45 +0000</pubDate>
		<dc:creator>Adrian Ward</dc:creator>
				<category><![CDATA[Dimensional Modelling]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[obiee]]></category>

		<guid isPermaLink="false">http://www.rittmanmead.com/?p=3968</guid>
		<description><![CDATA[An in-depth article on the analysis of facts, when those facts are also used as attributes.]]></description>
			<content:encoded><![CDATA[<p>As you will see from <a href="http://www.rittmanmead.com/2009/12/22/fantasy-football-and-obiee-part-1-you-can-be-statto/" target="_blank">Venkat&#8217;s Football blog</a>, we ran a demo of the OBIEE system at last years UKOUG.  The demo was based upon the English Football Premiership, and although I prefer rugby, using sports in samples is a great way to highlight the features of OBIEE.  It seems that some sports, such as Cricket, American Football and Tennis seem to compete on the number of statistics they can find in a match!</p>
<p>You don&#8217;t need to understand the English football league to understand the demo, however, for football managers there are dozens of facts that can be analysed, and can be related too.<br />
For example, you can run a request to show teams that are level at half time, but go on to lose the game in the second half.  As a coach you may draw from that fitness needs to be improved, along with concentration (more drinks?), and a better half time talk.</p>
<p>So you can use the &#8217;statistics&#8217; to help identify where things are going wrong, and when you are doing the right things, for example losing at away teams far away (change the travel arrangements?).</p>
<p>The great thing with sports stats is that you can also analyse your opponent to find their weaknesses &#8211; do they concede early goals (we have to come out strong and attacking from the whistle).</p>
<p>The other &#8216;interesting&#8217; thing about using sports results in OBIEE is that they clearly demonstrate how facts are sometimes measures and sometimes dimensional attributes&#8230;..</p>
<p>&#8212;</p>
<h3>Reporting on Fact based Dimensional Attributes</h3>
<p>Lets use an example to explore this:<br />
The exam question is this:</p>
<blockquote><p><em>How many games was my team losing at half time, but then went on to win.</em></p></blockquote>
<p>We will then drill into these games to try to understand the cause of this.</p>
<p>Remember the question for later!</p>
<p>The measures we have employed include:</p>
<ul>
<li>Goals scored</li>
<li>Home Team Score at Half Time</li>
<li>Home Team Score at Full time</li>
<li>Away Team Score at Half Time</li>
<li>Away Team Score at Full time</li>
<li>Home Team Red cards,</li>
<li>Home Team Yellow Cards,</li>
<li>etc</li>
</ul>
<p>These measures are set with an aggregation of SUM, but we could also set many of the other aggegations, such as AVERAGE.<br />
If you run the following request,</p>
<p style="text-align: center"><img class="size-medium wp-image-4237 aligncenter" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/3-252x300.png" alt="Home Stats" width="252" height="300" /></p>
<p>the SQL generated is:</p>
<address><span style="color: #000080">SELECT T6428.YEAR AS C1,</span></address>
<address><span style="color: #000080">T6428.HOMETEAM AS C2,</span></address>
<address><span style="color: #000080">&#8216;HOME&#8217; AS C3,</span></address>
<address><span style="color: #000080">SUM(T6428.FTHG) AS C4,</span></address>
<address><span style="color: #000080">SUM(T6428.FTAG) AS C5</span></address>
<address><span style="color: #000080">FROM</span></address>
<address><span style="color: #000080">PREMIER_LEAGUE T6428 /* HOME TEAM &#8211; PREMIER LEAGUE */</span></address>
<address><span style="color: #000080">WHERE ( T6428.YEAR = &#8216;2009&#8242; )</span></address>
<address><span style="color: #000080">GROUP BY T6428.HOMETEAM, T6428.YEAR</span></address>
<address><span style="color: #000080">ORDER BY C1, C2, C3</span></address>
<address></address>
<address><span style="color: #000080">** FTHG = Full Time Home Team Goals</span></address>
<address><span style="color: #000080">** FTAG = Full Time Away Team Goals</span></address>
<p>Note the &#8220;SUM(T6428.FTHG) AS C4&#8243; which is from the Sum Aggregate in the logical Column.</p>
<h2><span style="color: #000000">Quick Data Modelling Aside</span></h2>
<p style="padding-left: 30px">
<p style="padding-left: 30px">Before I go further a quick note on how the data could be modelled.</p>
<p style="padding-left: 30px">There are essentially three ways (I can quickly think of) we could model the &#8216;result&#8217; of a match.</p>
<p style="padding-left: 30px">
<ol style="padding-left: 30px">
<li>Capture the result in the &#8216;Match&#8217; fact record.<br />
Two Examples<br />
a) We could add a field called HTR &#8211; Half Time Result &#8211; and enter words or codes such as &#8216;Home Win&#8217; or &#8216;HW&#8217;.<br />
b) We could add field called HW_HT (short for Home Win Half Time) and put a <em>0</em> or <em>1</em> in if it true</li>
<li>No Results code &#8211; just capture the goals (let the reporting layer do the work)</li>
<li>Place the result codes in a fact table of their own.<br />
Create a table called MatchResults, with columns</li>
</ol>
<p style="padding-left: 60px">MATCH_ID,   RESULT_CODE,   RESULT</p>
<p style="padding-left: 60px">a sample set of record for a match could be -</p>
<p style="padding-left: 60px">123, HW_HT, 0</p>
<p style="padding-left: 60px">123, AW_HT, 0</p>
<p style="padding-left: 60px">123, DR_HT, 1</p>
<p style="padding-left: 30px">
<h3>Back to the scenario</h3>
<p>Let&#8217;s look at a Scenario 1(a) method (which is the chosen method for our Demo).</p>
<p>In the ETL Venkat has created a field called FTR &#8211; Full Time Result, which contains the values H (Home Team Wins), D (Draw) and A (Away Team Wins)</p>
<p>If we use this column in a report</p>
<p><img class="aligncenter size-full wp-image-4256" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/6.png" alt="6" width="455" height="543" /></p>
<address><span style="color: #000080">WITH</span></address>
<address><span style="color: #000080">SAWITH0 AS (select sum(case when T6428.FTR = &#8216;H&#8217; then 1 else 0 end ) as c1,</span></address>
<address><span style="color: #000080">T6428.YEAR as c2,</span></address>
<address><span style="color: #000080">T6428.HOMETEAM as c3,</span></address>
<address><span style="color: #000080">T6428.AWAYTEAM as c4,</span></address>
<address><span style="color: #000080">T6428.DATE1 as c5</span></address>
<address><span style="color: #000080">from</span></address>
<address><span style="color: #000080">PREMIER_LEAGUE T6428 /* Home Team &#8211; Premier League */</span></address>
<address><span style="color: #000080">where ( T6428.YEAR = &#8216;2009&#8242; )</span></address>
<address><span style="color: #000080">group by T6428.AWAYTEAM, T6428.DATE1, T6428.HOMETEAM, T6428.YEAR)</span></address>
<address><span style="color: #000080">select distinct SAWITH0.c2 as c1,</span></address>
<address><span style="color: #000080">SAWITH0.c3 as c2,</span></address>
<address><span style="color: #000080">SAWITH0.c4 as c3,</span></address>
<address><span style="color: #000080">SAWITH0.c5 as c4,</span></address>
<address><span style="color: #000080">&#8216;Home&#8217; as c5,</span></address>
<address><span style="color: #000080">SAWITH0.c1 as c6</span></address>
<address><span style="color: #000080">from</span></address>
<address><span style="color: #000080">SAWITH0</span></address>
<address><span style="color: #000080">order by c1, c2, c3, c4, c5</span></address>
<p>In Summary this is:</p>
<p><img class="aligncenter size-full wp-image-4257" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/7.png" alt="7" width="282" height="369" /></p>
<address><span style="color: #000080">select T6428.YEAR as c1,</span></address>
<address><span style="color: #000080">T6428.HOMETEAM as c2,</span></address>
<address><span style="color: #000080">&#8216;Home&#8217; as c3,</span></address>
<address><span style="color: #000080">sum(case when T6428.FTR = &#8216;H&#8217; then 1 else 0 end ) as c4</span></address>
<address><span style="color: #000080">from</span></address>
<address><span style="color: #000080">PREMIER_LEAGUE T6428 /* Home Team &#8211; Premier League */</span></address>
<address><span style="color: #000080">where ( T6428.YEAR = &#8216;2009&#8242; )</span></address>
<address><span style="color: #000080">group by T6428.HOMETEAM, T6428.YEAR</span></address>
<address><span style="color: #000080">order by c1, c2, c3</span></address>
<p><span style="color: #000080"><span style="color: #000000">Now let&#8217;s take a scenario</span> </span>2 where the ETL for football scores does not populate a set of result fields. This is often the case where database developers are not warehouse or star friendly, and only store the raw data.</p>
<p>So, in order to determine who is winning at half time we have to run a calculation. The choices of where you do this are numerous:</p>
<ol>
<li>In the database (Create a materialised or normal View)</li>
<li>In the rpd &#8211; Create a calculated field which looks at the scores</li>
<li>In a request &#8211; In a particular report</li>
</ol>
<p>The database option probably being the longest one to implement, but it will also be the most performant (if using an MV) when you come to running reports. Creating the calculation in the rpd means it is re-usable. Creating the calculation in the report is probably the easiest to get done in a short time.</p>
<p>Lets have a look at creating a request of home wins at full time.</p>
<p>Add, Year, Team Name, Wins at Full Time.</p>
<p style="text-align: center"><img class="size-medium wp-image-4239 aligncenter" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/4-218x300.png" alt="Get Wins" width="218" height="300" /></p>
<p>Wins at Full time =</p>
<p style="text-align: center"><img class="size-medium wp-image-4238 aligncenter" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/5-300x204.png" alt="Case Win" width="300" height="204" /></p>
<p>(CASE WHEN ((Home Team Score at Full Time &#8211; AWAY Team Score at Full Time)&gt;0) THEN 1 ELSE 0 END)</p>
<p>Which created the following SQL.</p>
<address><span style="color: #000080">WITH</span></address>
<address><span style="color: #000080">SAWITH0 AS (SELECT SUM(T6428.FTAG) AS C1,</span></address>
<address><span style="color: #000080">SUM(T6428.FTHG) AS C2,</span></address>
<address><span style="color: #000080">T6428.YEAR AS C3,</span></address>
<address><span style="color: #000080">T6428.HOMETEAM AS C4</span></address>
<address><span style="color: #000080">FROM</span></address>
<address><span style="color: #000080">PREMIER_LEAGUE T6428 /* HOME TEAM &#8211; PREMIER LEAGUE */</span></address>
<address><span style="color: #000080">WHERE ( T6428.YEAR = &#8216;2009&#8242; )</span></address>
<address><span style="color: #000080">GROUP BY T6428.HOMETEAM, T6428.YEAR)</span></address>
<address><span style="color: #000080">SELECT DISTINCT SAWITH0.C3 AS C1,</span></address>
<address><span style="color: #000080">SAWITH0.C4 AS C2,</span></address>
<address><span style="color: #000080">SAWITH0.C2 AS C3,</span></address>
<address><span style="color: #000080">SAWITH0.C1 AS C4,</span></address>
<address><span style="color: #000080">CASE WHEN SAWITH0.C2 &#8211; SAWITH0.C1 &gt; 0 THEN 1 ELSE 0 END AS C5</span></address>
<address><span style="color: #000080">FROM</span></address>
<address><span style="color: #000080">SAWITH0</span></address>
<address><span style="color: #000080">ORDER BY C1, C2</span></address>
<p>AH!, So the SQL generated <strong>did not give the right answer</strong>.</p>
<p>Is that what you expected? Did you definately know it was going to do that?</p>
<p>As you can see it SUMMED the Home Goals and Away goals for the season then looked at the case if sum(Home goals) is greater than sum(away goals). Therefore you do not get an answer for each match, so cannot get total matches won in the table.</p>
<h3>Why is this?</h3>
<p>The key difference between Scenario 1 and 2 is shown in the statements</p>
<p>The first method analysis of the Result runs on each Match record in the table, then sums the field</p>
<p>sum(case when T6428.FTR = &#8216;H&#8217; then 1 else 0 end ) as c4</p>
<p>The second method runs an analysis the summed fields</p>
<p>CASE WHEN SAWITH0.C2 &#8211; SAWITH0.C1 &gt; 0 THEN 1 ELSE 0 END AS C5</p>
<p>Now lets see if we can get a Scenario 2 to work.</p>
<p>Here is the query again, but with a secret weapon &#8211; The Pivot table</p>
<p style="text-align: center"><img class="size-medium wp-image-4240  aligncenter" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/10-200x300.png" alt="Get wins" width="200" height="300" /></p>
<p>.SQL produced is the same,</p>
<address><span style="color: #0000ff">WITH</span></address>
<address><span style="color: #0000ff">SAWITH0 AS (select sum(T6428.FTAG) as c1,</span></address>
<address><span style="color: #0000ff">sum(T6428.FTHG) as c2,</span></address>
<address><span style="color: #0000ff">T6428.YEAR as c3,</span></address>
<address><span style="color: #0000ff">T6428.HOMETEAM as c4,</span></address>
<address><span style="color: #0000ff">T6428.DATE1 as c5,</span></address>
<address><span style="color: #0000ff">T6428.AWAYTEAM as c6</span></address>
<address><span style="color: #0000ff">from</span></address>
<address><span style="color: #0000ff">PREMIER_LEAGUE T6428 /* Home Team &#8211; Premier League */</span></address>
<address><span style="color: #0000ff">where ( T6428.YEAR = &#8216;2009&#8242; )</span></address>
<address><span style="color: #0000ff">group by T6428.AWAYTEAM, T6428.DATE1, T6428.HOMETEAM, T6428.YEAR),</span></address>
<address><span style="color: #0000ff">SAWITH1 AS (select distinct SAWITH0.c1 as c1,</span></address>
<address><span style="color: #0000ff">SAWITH0.c2 as c2,</span></address>
<address><span style="color: #0000ff">SAWITH0.c3 as c3,</span></address>
<address><span style="color: #0000ff">SAWITH0.c4 as c4,</span></address>
<address><span style="color: #0000ff">SAWITH0.c5 as c5,</span></address>
<address><span style="color: #0000ff">&#8216;Home&#8217; as c6,</span></address>
<address><span style="color: #0000ff">SAWITH0.c6 as c7</span></address>
<address><span style="color: #0000ff">from</span></address>
<address><span style="color: #0000ff">SAWITH0)</span></address>
<address><span style="color: #0000ff">select distinct SAWITH1.c3 as c1,</span></address>
<address><span style="color: #0000ff">SAWITH1.c4 as c2,</span></address>
<address><span style="color: #0000ff">SAWITH1.c5 as c3,</span></address>
<address><span style="color: #0000ff">SAWITH1.c6 as c4,</span></address>
<address><span style="color: #0000ff">SAWITH1.c7 as c5,</span></address>
<address><span style="color: #0000ff">SAWITH1.c2 as c6,</span></address>
<address><span style="color: #0000ff">SAWITH1.c1 as c7,</span></address>
<address><span style="color: #0000ff">case when SAWITH1.c2 &#8211; SAWITH1.c1 &gt; 0 then 1 else 0 end as c8</span></address>
<address><span style="color: #0000ff">from</span></address>
<address><span style="color: #0000ff">SAWITH1</span></address>
<address><span style="color: #0000ff">order by c1, c2, c3, c4, c5</span></address>
<p>This time the query is the same, but I have put all the details into the table so that each match record is analysed, then used a pivot table to display the results</p>
<p style="text-align: center"><img class="size-medium wp-image-4241 aligncenter" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/02/10a-300x138.png" alt="The Pivot" width="300" height="138" /></p>
<blockquote><p>So the secret is to make sure that the calculations are done at the detail row level to get the right answer, then have the BI server add the rows for you.</p></blockquote>
<p>The exam question can therefore be answered by creating a query with all the necessary calculations, Half time losing (make =1)  minus full time winning (make = 0). sum the result in a pivot.</p>
<p>So the data can be analysed by treating the fact like an attribute of the match.  My favourite method to model this is to create the resultant fields &#8211; HT_HW (0/1), FT_HW(0/1) on the table and add these to a logical dimension. Then expose the dimension table and, Hey Presto your facts are acting like dimensional attributes.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rittmanmead.com/2010/02/02/fantasy-football-when-is-a-fact-not-a-fact/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Oracle Fusion Middleware 11g &#8211; BI ADF Components &#8211; First impressions</title>
		<link>http://www.rittmanmead.com/2010/01/28/oracle-fusion-middleware-11g-bi-adf-components-first-impressions/</link>
		<comments>http://www.rittmanmead.com/2010/01/28/oracle-fusion-middleware-11g-bi-adf-components-first-impressions/#comments</comments>
		<pubDate>Thu, 28 Jan 2010 18:23:51 +0000</pubDate>
		<dc:creator>Venkatakrishnan J</dc:creator>
				<category><![CDATA[FMW]]></category>
		<category><![CDATA[Oracle BI Suite EE]]></category>

		<guid isPermaLink="false">http://www.rittmanmead.com/?p=4235</guid>
		<description><![CDATA[One of the few things that i have been working on this week is in understanding how the recently released Fusion Middleware 11g will influence Oracle BI EE in the near future. As was demonstrated &#38; presented in the last Open World by Oracle, the strategic direction of Oracle is to use Fusion Middleware 11g [...]]]></description>
			<content:encoded><![CDATA[<p>One of the few things that i have been working on this week is in understanding how the recently released Fusion Middleware 11g will influence Oracle BI EE in the near future. As was demonstrated &amp; presented in the last Open World by Oracle, the strategic direction of Oracle is to use Fusion Middleware 11g as the base for all Oracle products including Business Intelligence going forward. FMW 11g has an excellent set of components like Visualizations, Custom Graphs, Table &amp; Pivot View Components, Hierarchy Viewer etc which can all add value to the existing feature set of BI EE. If Oracle can somehow make them as pluggable components in future releases, it will make it a lot easier to extend BI EE.</p>
<p>One of the first integrations that i noticed between Fusion Middleware and BI EE was when JDeveloper 11g Tech Preview 4 was released almost 2 years back. I had blogged about it sometime back <a href="http://oraclebizint.wordpress.com/2008/05/05/oracle-bi-ee-101332-and-jdeveloper-11g-tech-preview-34-new-integration-features-public-bi-ee-pages-without-authentication-noauthgo-parameter/" target="_blank">here</a>. This integration was very promising wherein every report in BI EE Web Catalog was exposed as a view object. So in effect, from within JDeveloper one can easily apply ADF visualizations to an existing BI EE report/dashboard. This integration was very similar to the BI Publisher &#8211; BI EE integration where instead of a template, ADF visualization is applied. Unfortunately, this feature does not exist anymore in the production release of JDeveloper 11g. Though it does not exist as a feature now, there are ways to still expose them within JDeveloper. I will cover them in future blog entries.</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 12" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture12.png" border="0" alt="Picture 12" width="170" height="315" /></p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 13" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture131.png" border="0" alt="Picture 13" width="330" height="315" /></p>
<p>In the current release of Fusion Middleware 11g, there are quite a few BI specific visualizations that have been made available. All of these can be used even on existing BI EE 10g installations. But the only downside is, there will be quite a bit of coding involved to tie BI EE 10g with the FMW 11g graphs. Hopefully this should be made easier with BI EE 11g.</p>
<p>I will basically highlight some of the interesting ADF Visualization components specific to Business Intelligence in this blog entry here. Many of the graphs shown below are available as part of a sample application that needs to be obtained from OTN. All these(base components for the charts/graphs) are available out of the box with the FMW 11g installation.</p>
<p><strong>Custom Gauges:</strong></p>
<p>FMW 11g adds some significant number of Gauge components. I have listed the important ones below. All these are very interactive like the Corda Charts that we are used to seeing in BI EE. ADF Gauges are based on SVG and hence the drills are supported here as well.</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 14" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture141.png" border="0" alt="Picture 14" width="347" height="315" /></p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 15" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture152.png" border="0" alt="Picture 15" width="504" height="179" /></p>
<p><strong>Graph Visualizations:</strong></p>
<p>FMW 11g supports 2 main features in any graph</p>
<p>1. Custom Annotations can be added<br />
2. Individual data points can be moved (drag and drop) for better visualization</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 17" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture172.png" border="0" alt="Picture 17" width="504" height="230" /></p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 17" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture173.png" border="0" alt="Picture 17" width="504" height="201" /></p>
<p>Custom panel splitters are supported as well. One can essentially have 4 graphs in a page and then hide/unhide them in a pane layout as shown below</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 18" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture182.png" border="0" alt="Picture 18" width="390" height="315" /></p>
<p>Its very interesting to note that time based interactivity in the graphs have been added. For example, one can choose a time period within a master graph, the child graphs will change automatically.</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 19" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture192.png" border="0" alt="Picture 19" width="504" height="193" /></p>
<p>There is also an inline graph component called Spark Charts. These are charts that are embedded as a cell object in a table/pivot view.</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 20" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture202.png" border="0" alt="Picture 20" width="206" height="156" /></p>
<p><strong>Pivot Tables: </strong></p>
<p>This is one area where i am seeing significant changes to the way BI EE 10g pivot table and FMW11g Pivots. Some interesting features of FMW11g pivot tables are</p>
<p>1. Pivot Table Heat Maps &amp; Conditional Formatting</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 21" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture211.png" border="0" alt="Picture 21" width="253" height="167" /></p>
<p>2. Ability to embed charts (Spark Charts &amp; Gauges) in the pivot tables</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 22" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture221.png" border="0" alt="Picture 22" width="439" height="304" /></p>
<p>3. Ability to drag and drop the columns outside of the edit layout. Also ability to edit cells (potential for writebacks)</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 24" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture241.png" border="0" alt="Picture 24" width="504" height="108" /></p>
<p><strong>Gantt Charts:</strong></p>
<p>This is a significant addition to the list of supported graphs in the FMW 11g. Quite a lot of visualizations are supported on the Gantt Charts</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 23" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture231.png" border="0" alt="Picture 23" width="504" height="133" /></p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 24" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture242.png" border="0" alt="Picture 24" width="504" height="176" /></p>
<p>There is another nice add-on to the normal Gantt charts i.e one can track Resource utilization as a stacked bar against Time as the base.</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 25" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture251.png" border="0" alt="Picture 25" width="504" height="125" /></p>
<p><strong>Hierarchy Viewer:</strong></p>
<p>This visualization is probably one of the highlights of FMW 11g. Instead of a normal hierarchy drills from Pivots/tables, this visualization can provide visual hierarchical drills as shown below</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 26" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture261.png" border="0" alt="Picture 26" width="504" height="314" /></p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 28" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture281.png" border="0" alt="Picture 28" width="504" height="216" /></p>
<p><strong>Mapviewer Integration:</strong></p>
<p>This is another area where FMW 11g adds a lot of value. It is now possible to directly reuse Maps built out of Mapviewer and render them along with BI components within the FMW framework</p>
<p align="center"><img style="border-top-width: 0px; display: block; border-left-width: 0px; float: none; border-bottom-width: 0px; margin-left: auto; margin-right: auto; border-right-width: 0px" title="Picture 28" src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/Picture282.png" border="0" alt="Picture 28" width="504" height="306" /></p>
<p>There are other areas as well where every graph/chart has improved. For example, now FMW 11g supports a set of attributes that can be modified uniformly for all the graphs. It also provides Master-Detail forms/reports. On a whole, to me, it looks like Oracle has indeed spent quite a bit of time and effort to get the BI framework in FMW ready. Now if only these can be reused out of the box directly from within the BI EE in future releases, then it could add significant dimension to the way we do BI reporting. I guess only time will tell on how these components eventually get into BI EE.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rittmanmead.com/2010/01/28/oracle-fusion-middleware-11g-bi-adf-components-first-impressions/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>RMOUG Training Days</title>
		<link>http://www.rittmanmead.com/2010/01/27/rmoug-training-days/</link>
		<comments>http://www.rittmanmead.com/2010/01/27/rmoug-training-days/#comments</comments>
		<pubDate>Wed, 27 Jan 2010 20:03:48 +0000</pubDate>
		<dc:creator>Stewart Bryson</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.rittmanmead.com/?p=4193</guid>
		<description><![CDATA[The annual RMOUG Training Days event takes place on February 17th and 18th in Denver, CO, with some additional university sessions taking place on February 16th. I am excited to be co-presenting with Mark Rittman on A DBA and Developers&#8217; Guide to Oracle Warehouse Builder 11gR2. Quite often, when we speak or train on OWB, [...]]]></description>
			<content:encoded><![CDATA[<p>The annual <a href="http://rmoug.org/training.htm">RMOUG Training Days</a> event takes place on February 17th and 18th in Denver, CO, with some additional university sessions taking place on February 16th. I am excited to be co-presenting with Mark Rittman on <a href="http://www.technicalconferencesolutions.com/pls/caat/caat_abstract_reports.display_presenter_abstract?conference_id=62&amp;presenter_id=261&amp;abstract_id=172">A DBA and Developers&#8217; Guide to Oracle Warehouse Builder 11gR2</a>. Quite often, when we speak or train on OWB, it is slanted toward BI architects, ETL developers, etc. In this session, however, Mark and I will be demonstrating some of the new 11gR2 features of OWB, approaching the subject from a application-neutral perspective. So perhaps you want to consider using OWB as more of an integration tool, or just need to do your average, run-of-the-mill database development, OWB might just be the tool for you. Additionally, there is a new feature in OWB called <a href="http://www.rittmanmead.com/2009/09/21/code-templates-in-owb11gr2-part-2-introduction-to-code-template-mappings/">code template mappings</a> that allows DBAs and database architects to participate in the ETL lifecycle with some database best-practices, without having to actually DO the ETL development.</p>
<p>This will be my first time attending the Rocky Mountain Oracle Users Group event, and I am excited to see a strong showing from some of the community staples. Have a look at the <a href="http://www.technicalconferencesolutions.com/pls/caat/caat_abstract_reports.schedule?conference_id=62">agenda</a> and see some of the presentations that will be going on at the largest Oracle regional user group event in the United States. You could do worse than spending a few days in beautiful Colorado, after all.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rittmanmead.com/2010/01/27/rmoug-training-days/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The BI Survey 9 &#8211; Fieldwork Closes on Sunday</title>
		<link>http://www.rittmanmead.com/2010/01/27/the-bi-survey-9-fieldwork-closes-on-sunday/</link>
		<comments>http://www.rittmanmead.com/2010/01/27/the-bi-survey-9-fieldwork-closes-on-sunday/#comments</comments>
		<pubDate>Wed, 27 Jan 2010 10:58:38 +0000</pubDate>
		<dc:creator>Mark Rittman</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.rittmanmead.com/?p=4190</guid>
		<description><![CDATA[[Fieldwork for the BI Survey 9, an independent survey of BI customers and partners, closes its fieldwork on Sunday 31st January. It's important that we get a suitable number of Essbase, OBIEE, OLAP and Discoverer users completing the survey, so please visit the site and fill it in if you've not done so already. Thanks [...]]]></description>
			<content:encoded><![CDATA[<p><em>[Fieldwork for the BI Survey 9, an independent survey of BI customers and partners, closes its fieldwork on Sunday 31st January. It's important that we get a suitable number of Essbase, OBIEE, OLAP and Discoverer users completing the survey, so please visit the site and fill it in if you've not done so already. Thanks - MR]</em></p>
<p style="text-align:center;"><img src="http://www.rittmanmead.com/wp2/wp-content/uploads/2009/11/dyna_banner_bisurvey9-1.jpg" height="75" width="500" border="1" hspace="4" vspace="4" alt="Dyna Banner Bisurvey9-1" /></p>
<p><strong>&#8220;The BI Survey 9: The Customer Verdict</strong></p>
<p>We would very much welcome your participation in &#8216;The BI Survey 9: The Customer Verdict&#8217;, the world&#8217;s largest survey of business intelligence (BI) and performance management (PM) users (formerly known as The OLAP Survey).</p>
<p>As a participant, you will:</p>
<ul>
<li>Receive a summary of the results from the full survey</li>
<li>Be entered into a draw to win one of ten $50 Amazon vouchers</li>
<li>Ensure that your experiences are included in the final analyses</li>
</ul>
<p>To take part in the survey on-line, visit: <a href="http://digiumenterprise.com/answer?link=249-KP9DYABR">http://digiumenterprise.com/answer?link=270-5J9MMB9M<br />
</a><br />
BARC&#8217;s annual survey obtains input from a large number of organizations in order to better understand their buying decisions, the implementation cycle and the business benefits achieved.</p>
<p>Both business and technical users, as well as vendors and consultants, are welcome to participate. If you are answering as a consultant, please answer the questions (including the demographic questions) from your client&#8217;s perspective; we will ask you separately about your own firm.</p>
<p>The BI Survey has always adopted a vendor-independent stance. While vendors assist by inviting users to participate in the Survey, Business Application Research Center (BARC) &#8211; the publisher &#8211; does not accept vendor sponsorship of the Survey, and the results are analyzed and published without any vendor involvement.</p>
<p>You will be able to answer questions on your usage of a BI product from any vendor. Your answers will only be used anonymously, and your personal details will never be passed on to vendors or other third parties.</p>
<p>The survey should take about 15-20 minutes to complete</p>
<p>* BARC (Business Application Research Center) is a leading independent software industry analyst specializing in Data Management and Business Intelligence. For more information on BARC please visit <a href="http://www.barc.de/index.php?id=6&#038;L=1%22%20%5Co%20%22BARC%20Homepage">The BARC website</a>, <a href="http://www.bi-survey.com">www.bi-survey.com</a> and <a href="http://www.bi-verdict.com%22%20%5Ct%20%22_blank">www.BI-Verdict.com</a>&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rittmanmead.com/2010/01/27/the-bi-survey-9-fieldwork-closes-on-sunday/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BI Forum 2010 Abstract Voting Now Open</title>
		<link>http://www.rittmanmead.com/2010/01/25/bi-forum-2010-abstract-voting-now-open/</link>
		<comments>http://www.rittmanmead.com/2010/01/25/bi-forum-2010-abstract-voting-now-open/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 20:18:34 +0000</pubDate>
		<dc:creator>Mark Rittman</dc:creator>
				<category><![CDATA[User Groups & Conferences]]></category>

		<guid isPermaLink="false">http://www.rittmanmead.com/?p=4184</guid>
		<description><![CDATA[If you&#8217;re considering coming along to the BI Forum 2010 we&#8217;ll be holding in Brighton in May 2010, we&#8217;d be interested in hearing your opinion on what sessions we&#8217;ll be running. The call for papers is now closed and we have 27 potential sessions, from speakers around the world. The content covers OBIEE, Essbase, ODI [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re considering coming along to the BI Forum 2010 we&#8217;ll be holding in Brighton in May 2010, we&#8217;d be interested in hearing your opinion on what sessions we&#8217;ll be running. The call for papers is now closed and we have 27 potential sessions, from speakers around the world. The content covers OBIEE, Essbase, ODI and OWB, with content aimed at experienced developers, and the abstract voting form can be found at the following address:</p>
<p><a href="http://www.zoomerang.com/Survey/?p=WEB22A5U9QD93G">http://www.zoomerang.com/Survey/?p=WEB22A5U9QD93G</a></p>
<p><strong>UPDATE:</strong> We missed one off &#8211; sorry:</p>
<p><a href="http://www.zoomerang.com/Survey/?p=WEB22A63S9HTWZ">http://www.zoomerang.com/Survey/?p=WEB22A63S9HTWZ</a></p>
<p>If you&#8217;re one of the potential speakers, please don&#8217;t vote for your own paper (this keeps scoring consistent across all speakers). We&#8217;ll keep the vote open for seven days from now, and contact the successful speakers at the start of February. Once all is in place we&#8217;ll then open the event for registration towards the middle of May. Thanks again to everyone who has shown interest,  and for the potential speakers who have submitted some excellent abstracts.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rittmanmead.com/2010/01/25/bi-forum-2010-abstract-voting-now-open/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Heat Maps in OBIEE</title>
		<link>http://www.rittmanmead.com/2010/01/22/heat-maps-in-obiee/</link>
		<comments>http://www.rittmanmead.com/2010/01/22/heat-maps-in-obiee/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 21:06:08 +0000</pubDate>
		<dc:creator>Peter Scott</dc:creator>
				<category><![CDATA[Oracle BI Suite EE]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.rittmanmead.com/?p=4169</guid>
		<description><![CDATA[OBIEE 10.1.3.4.1 has a host of ways to add visual impact to reported data to aid its interpretation. But some things are not so easy to achieve, or at least not by just clicking on a few format buttons on the Answers web page.
One of my customers had the need to report a day&#8217;s figures [...]]]></description>
			<content:encoded><![CDATA[<p>OBIEE 10.1.3.4.1 has a host of ways to add visual impact to reported data to aid its interpretation. But some things are not so easy to achieve, or at least not by just clicking on a few format buttons on the Answers web page.</p>
<p>One of my customers had the need to report a day&#8217;s figures and colour the results based on change since yesterday. I also had three additional design challenges to meet: not to change the RPD (this is only a proof of concept, RPD changes might come later), avoid having to laboriously conditionally format each coloured cell (the colour rules could become very complex and based on multiple columns) and allow the use of &#8220;normal&#8221; and pivot tables on the dashboard.</p>
<p>Firstly, as I am looking at the difference between the a measure over two days I can not use a pivot report for this as it is not possible to calculate differences between measure columns in the pivot. But we can use the &#8216;FILTER&#8217; button on the column formula editor to restrict the values returned to just those that match the filter. By doing this twice, once for each day of interest, we get two columns in the same Answers Request TABLE view that we can do the maths on. Here we need to calculate the percentage difference between the two values.</p>
<p>Now I can calculate the values I need for my heat map &#8211; the day&#8217;s measures, and the percentage change since yesterday. Next I need to colour in the cell backgrounds.</p>
<p>Of course it very possible to just use conditional formatting, but this gets quite unwieldy with complex cell colour rules, and of course the request to make the colour mapping reusable across multiple Answers requests and dashboards. I decided to tackle the problem by adding a text column to the request and changing its format to HTML. To change the background colour of a cell you need to make the cell contain the following HTML:</p>
<pre>&lt;div style="background-color: rgb('|| cast(255*RND() as varchar(3))||','||cast(255*RND() as varchar(3))||',cast(255*RND() as varchar(3))|| ');" &gt; -some value to output' || &lt;/div&gt;'</pre>
<p>You must output something in the cell as OBIEE does not colour in NULL values. I decided to use the RGB() form of the colour selector as it is probably simpler to calculate three numeric values than to build colour codes in hexadecimal.</p>
<p>Although it is feasible to code this colour mapping in OBIEE it is a lot of effort. Here I simplified things greatly by writing a database function that takes the value to display and a value that controls the colour (and here it is simply percentage change over two days) as the two arguments and returns a varchar2 string that formats the cell. Although the colouring coding algorithm can be as complex as you like ultimately we populate a string and return it.</p>
<pre>[code omitted]
vHTML_STRING:='&lt;div style="background-color: rgb('||vRED||','||vGREEN||','||vBLUE||')" &gt;'||TO_CHAR(pValue,'FM999,999,999,999')||' &lt;/div&gt;'
return vHTML_STRING;</pre>
<p>To use this we simply set the cell contents to be the results of the OBIEE EVALUATE</p>
<pre>Evaluate('ORCL.F_my_colour_map(%1,%2)' as varchar(100), [some OBIEE expression that evaluates to the colour],[some other expression that gives the value to display]))</pre>
<p>function formatted as HTML.</p>
<p>Of course, this method is only suitable for the current OBIEE release, older versions may not have 'EVALUATE' and  the future OBIEE 11 may not behave in the same way with rendering HTML within Answers tables.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rittmanmead.com/2010/01/22/heat-maps-in-obiee/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Data Rules and Error Handling in Warehouse Builder 10gR2/11gR2</title>
		<link>http://www.rittmanmead.com/2010/01/22/data-rules-and-error-handling-in-warehouse-builder-10gr211gr2/</link>
		<comments>http://www.rittmanmead.com/2010/01/22/data-rules-and-error-handling-in-warehouse-builder-10gr211gr2/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 09:12:59 +0000</pubDate>
		<dc:creator>Mark Rittman</dc:creator>
				<category><![CDATA[Oracle Warehouse Builder]]></category>

		<guid isPermaLink="false">http://www.rittmanmead.com/2010/01/22/data-rules-and-error-handling-in-warehouse-builder-10gr211gr2/</guid>
		<description><![CDATA[One of the less well-known features in recent releases of Warehouse Builder is Data Rules, and how they can help you gracefully handle consistency issues in your data. Data Rules act as virtual constraints on your data and add error handling tables to your mappings to allow you to divert off, or reprocess data that [...]]]></description>
			<content:encoded><![CDATA[<p>One of the less well-known features in recent releases of Warehouse Builder is Data Rules, and how they can help you gracefully handle consistency issues in your data. Data Rules act as virtual constraints on your data and add error handling tables to your mappings to allow you to divert off, or reprocess data that fails one or more consistency checks. Let&#8217;s take a look at an example to see how they work.</p>
<p>To create an example, we have a table called CUSTOMERS_TGT that has a column called GENDER. We want to enforce a data rule that says this column cannot be null. However we want our Warehouse Builder mapping to catch rows coming in that have null in this column, and replace the nulls with an &#8220;Unknown&#8221; value. To start this process we open up the target table in the Data Object Editor (I&#8217;m using version 11gR1 of Warehouse Builder, but the feature works the same in 10gR2 and 11gR2), click on the <strong>Data Rules</strong> tab at the bottom, and click on the <strong>Apply Rule</strong> button.</p>
<p style="text-align:center;"><img src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/dq1-1.jpg" height="404" width="500" border="0" hspace="4" vspace="4" alt="Dq1-1" /></p>
<p>I am then presented with the first page of a wizard, and then I&#8217;m shown a list of pre-defined data quality checks that I can select from. I select the <strong>NOT NULL</strong> check and press <strong>Next</strong> to continue, I then name the data quality check and are then asked which table column the check should be &#8220;bound&#8221; to. I select the <strong>GENDER</strong> column and press <strong>Next</strong> to continue.</p>
<p style="text-align:center;"><img src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/dq3.jpg" height="400" width="500" border="0" hspace="4" vspace="4" alt="Dq3" /></p>
<p>Once the wizard is complete, my table now has an entry under Data Rules, with this Not Null rule shown as applying and bound to the GENDER column.</p>
<p style="text-align:center;"><img src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/dq4.jpg" height="406" width="500" border="0" hspace="4" vspace="4" alt="Dq4" /></p>
<p>I then use the Control Center Manager to redeploy this table, not because the new data rule has caused a physical NOT NULL constraint to be added to the target table (all of these constraints are &#8220;virtual&#8221; and handled within the Warehouse Builder mapping), but because of a &#8220;Shadow Table&#8221; that needs to be deployed alongside the target table to handle the errors. You don&#8217;t see this table listed in the set of tables within the OWB database module, it only appears as a script when you go to redeploy the table, but it&#8217;s important you deploy this (or create your own of the same definition) otherwise the mappings later on will fail.</p>
<p style="text-align:center;"><img src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/dq9.jpg" height="259" width="465" border="0" hspace="4" vspace="4" alt="Dq9" /></p>
<p>Note also that your target table shouldn&#8217;t have a real NOT NULL constraint on it , as this can cause your mapping to fail even when error handling is enabled in the mapping, as the real constrain gets in there first before your mapping can gracefully handle the error. The target table should however have a primary key as this is used later on when moving incoming rows around that fail the error check.</p>
<p>Over to the mapping editor now, where I&#8217;ve got a simple mapping that loads from a source table into this target table. Note that my target table, the one above, has some extra rows in the table operator now due to the data rule that I&#8217;ve added to it.</p>
<p style="text-align:center;"><img src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/dq6.jpg" height="298" width="500" border="0" hspace="4" vspace="4" alt="Dq6" /></p>
<p>As you can see, the target table has some extra rows that are used to hold any incoming rows that fail data rule checks, with the ERR$$$ columns holding the reason for the error. Before the error handling will take place though you need to tell OWB, via the target table properties editor, to move the errors to the error handling table rather than just ignore, or report on them.</p>
<p style="text-align:center;"><img src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/dq7.jpg" height="219" width="334" border="0" hspace="4" vspace="4" alt="Dq7" /></p>
<p>Note also the Error Table section of the table properties, which lets you substitute your own, pre-built error handling table if you want to, and to fine-tune how error records are stored in the table.</p>
<p style="text-align:center;"><img src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/dq10.jpg" height="205" width="330" border="0" hspace="4" vspace="4" alt="Dq10" /></p>
<p>So now we&#8217;re ready to go. I deploy the mapping (if the mapping deployment fails because of a table it can&#8217;t find, check that you&#8217;ve deployed the error (shadow) table mentioned above) and then run it. Even though my incoming data had one row with a null value in the GENDER column, the mapping completes successfully.</p>
<p style="text-align:center;"><img src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/dq11.jpg" height="150" width="445" border="0" hspace="4" vspace="4" alt="Dq11" /></p>
<p>However the Job Details page shows that some incoming data was diverted to my error handling table.</p>
<p style="text-align:center;"><img src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/dq12.jpg" height="164" width="533" border="0" hspace="4" vspace="4" alt="Dq12" /></p>
<p>SQL Developer shows that the new error handling table does in fact contain the row that&#8217;s failed the data quality check.</p>
<p style="text-align:center;"><img src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/dq13.jpg" height="157" width="500" border="0" hspace="4" vspace="4" alt="Dq13" /></p>
<p>Checking the target table shows that all of the remaining rows are compliant with the NOT NULL data rule.</p>
<p>But what if we wanted to correct data that failed the check, as well as record it in this error handling table. Well, we can take the output of the error rows in the target table operator, apply a transformation to it and then load just these back into the target table, if there&#8217;s a &#8220;not known&#8221; value for example that we wish to apply to values that would otherwise be null.</p>
<p style="text-align:center;"><img src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/dq14.jpg" height="278" width="500" border="0" hspace="4" vspace="4" alt="Dq14" /></p>
<p>Make sure you set the error handling action of this new target table operator to also reject rows that fail the not null check (otherwise you might inadvertently add the row back with data that might still fail the data rule check).</p>
<p>Running the mapping again shows it executing correctly, but this time if I check SQL Developer, I can see a new row appearing that has had its otherwise null GENDER value converted to a &#8220;U&#8221;, for unknown.</p>
<p style="text-align:center;"><img src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/dq15.jpg" height="201" width="362" border="0" hspace="4" vspace="4" alt="Dq15" /></p>
<p>The mapping execution still added a row to the error table though for this row, so that I can see where the mapping has corrected data in the background.</p>
<p style="text-align:center;"><img src="http://www.rittmanmead.com/wp2/wp-content/uploads/2010/01/dq16.jpg" height="158" width="500" border="0" hspace="4" vspace="4" alt="Dq16" /></p>
<p>The process works in the same way for other data rules you might apply, such as domain check rules, foreign key rules, &#8220;not number&#8221; rules and so forth. <del datetime="2010-01-27T21:53:04+00:00">One thing to bear in mind though is that these mappings run in PL/SQL (as opposed to SQL, set-based) mode and therefore might not perform as well as ones without data rules applied</del> <em>[This was fixed from 10.2.0.3, see the note from David Allen in the comments below, these mappings now run set-based in the same way as other mappings]</em>. However if you think about the benefits in terms of graceful error handling, the &#8220;self-documenting&#8221; nature of mappings that use this feature and so on, it&#8217;s certainly a good way of handling data quality issues in your staging or integration layer before bulk-loading the data into your main warehouse tables.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rittmanmead.com/2010/01/22/data-rules-and-error-handling-in-warehouse-builder-10gr211gr2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
