<?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>BI-Quotient</title>
	<atom:link href="http://www.business-intelligence-quotient.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.business-intelligence-quotient.com</link>
	<description>Intelligent BI.</description>
	<lastBuildDate>Sat, 15 Jun 2013 07:42:52 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.2</generator>
		<item>
		<title>ODI 11g Cookbook &#8211; The leading ETL tool now also has the best ETL book</title>
		<link>http://www.business-intelligence-quotient.com/?p=1919</link>
		<comments>http://www.business-intelligence-quotient.com/?p=1919#comments</comments>
		<pubDate>Sat, 15 Jun 2013 07:40:42 +0000</pubDate>
		<dc:creator>Uli Bethke</dc:creator>
				<category><![CDATA[Oracle Data Integrator (ODI)]]></category>
		<category><![CDATA[etl book]]></category>
		<category><![CDATA[odi]]></category>
		<category><![CDATA[odi 11g book]]></category>
		<category><![CDATA[ODI 11g cookbook]]></category>
		<category><![CDATA[odi book]]></category>
		<category><![CDATA[ODI cookbook]]></category>

		<guid isPermaLink="false">http://www.business-intelligence-quotient.com/?p=1919</guid>
		<description><![CDATA[I don&#8217;t know too many books or movies where the sequel is...]]></description>
			<content:encoded><![CDATA[<p>I don&#8217;t know too many books or movies where the sequel is better than the original. The <a href="http://www.packtpub.com/oracle-data-integrator-11g-cookbook/book" title="ODI 11g cookbook" target="_blank">ODI 11g cookbook</a> is such a rare case. It is stuffed with 60 valuable recipes that every ODI developer should know. Apart from the value of these recipes in their own right they also showcase the flexibility of ODI and can be transfered to other problems.</p>
<p>My favourite chapters are; Knowledge Module Internals, Advanced Coding Techniques, Advanced Topology, and Using Variables.</p>
<p>A big thank you to the ODI product management team for sharing their insights.</p>
<img src="http://www.business-intelligence-quotient.com/?ak_action=api_record_view&id=1919&type=feed" alt="" /><h3  class="related_post_title"></br>Related posts</h3><ul class="related_post"><li>June 14, 2011 -- <a href="http://www.business-intelligence-quotient.com/?p=1328" title="ODI 11g book announced for July">ODI 11g book announced for July</a><br /><small>The Oracle Data Integrator 11g: Getting Started book has been announced for 31 July.

For details ...</small></li><li>October 22, 2012 -- <a href="http://www.business-intelligence-quotient.com/?p=1678" title="How to query a whole schema or even database?! This tip will save you hours and hours of boring work.">How to query a whole schema or even database?! This tip will save you hours and hours of boring work.</a><br /><small>I really like this tip especially its simplicity. It has saved me hours and hours of mind numbing wo...</small></li><li>March 11, 2011 -- <a href="http://www.business-intelligence-quotient.com/?p=1187" title="Load Knowledge Module Oracle to Oracle using database links">Load Knowledge Module Oracle to Oracle using database links</a><br /><small>ODI comes with an LKM to extract data from another Oracle database instance using db links via a vie...</small></li><li>December 3, 2010 -- <a href="http://www.business-intelligence-quotient.com/?p=1123" title="Accessing a mapped network drive with the ODI agent as a Windows service">Accessing a mapped network drive with the ODI agent as a Windows service</a><br /><small>The problem

The other day we had a requirement to extract data from an Access database on a mappe...</small></li><li>September 9, 2010 -- <a href="http://www.business-intelligence-quotient.com/?p=1045" title="Subselect, derived tables, and subqueries in ODI 11G">Subselect, derived tables, and subqueries in ODI 11G</a><br /><small>I think one of the best new features in ODI 11G is the subselect/subquery feature. In ODI 10 this co...</small></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.business-intelligence-quotient.com/?feed=rss2&#038;p=1919</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using ODI user functions to dynamically inject SQL into Interfaces</title>
		<link>http://www.business-intelligence-quotient.com/?p=1831</link>
		<comments>http://www.business-intelligence-quotient.com/?p=1831#comments</comments>
		<pubDate>Sun, 19 May 2013 22:42:06 +0000</pubDate>
		<dc:creator>Maciek</dc:creator>
				<category><![CDATA[Oracle Data Integrator (ODI)]]></category>
		<category><![CDATA[Training]]></category>

		<guid isPermaLink="false">http://www.business-intelligence-quotient.com/?p=1831</guid>
		<description><![CDATA[I’d like to share with you a recipe that demonstrates the power...]]></description>
			<content:encoded><![CDATA[<p dir="ltr">I’d like to share with you a recipe that demonstrates the power which the combination of ODI functions and Java BeanShell scripting techniques can provide.<br />
<span style="font-size: 13px;">Before I do so I will briefly describe the issue we recently had as a background for the use case.</span></p>
<p><span style="font-size: 13px;">Doesn’t matter which programming language or tool you use, it’s a widely known good practice not to hardcode static values into your code.<br />
</span><span style="font-size: 13px;">I’m talking here about various ‘configuration’ like values used within the code itself: thresholds, whitelists, blacklists, capex values etc..<br />
</span><span style="font-size: 13px;">During the code development phase those may very well seem static but later when product has gone live it is often required to adjust them which may even result in a hotfix case in the worst scenario.<br />
</span><span style="font-size: 13px;">To prevent it the values can be provided in many alternative ways including registry, ini and XML files or just anything sourced from network connection.<br />
</span><span style="font-size: 13px;">The ODI is no exception here and the generic purpose parameter table seem like the natural way to handle such situations.</span></p>
<p><span style="font-size: 13px;">The problem may occur when such value is to be used in an ODI interface directly.<br />
</span><span style="font-size: 13px;">In the case we had the large table had to be filtered using such metadata stored parameter.<br />
</span><span style="font-size: 13px;">One way to do this would be to pull in that table directly into the interface.<br />
</span><span style="font-size: 13px;">It could be then used in the join:</span></p>
<p><strong><strong><img class="aligncenter" src="https://lh5.googleusercontent.com/Hvi3sXXS29SKVm4Apsts0rUtNrnWKxl-9pSzEbJxuDDP5_rGTLrfh7DgHUOKcxe_sFmwOGy34M4Qk6gDsXaMNRH3S37M6bB1trDeMllE0qRW-iHKQvZWnHtWaA01twTOxQ" alt="" width="460" height="199" /><br />
</strong></strong></p>
<p dir="ltr">Unfortunately, as would really expect, the join condition:</p>
<p><span style="font-size: small;"><span style="font-family: Consolas;"><span style="color: #000080;">DS.DAY_DATE&gt;to_date(P.VALUE,</span><span style="color: #0000ff;">&#8216;YYYY-MM-DD&#8217;</span><span style="color: #000080;">) </span><span style="color: #008080;">AND</span><span style="color: #000080;"> </span><span style="color: #008080;">KEY</span><span style="color: #000080;">=</span><span style="color: #0000ff;">&#8216;LAST_PROGRESS_DATE&#8217;</span></span></span></p>
<p dir="ltr"><span style="font-size: 13px;">doesn’t make a great query execution plan:</span></p>
<p><strong><strong><img class="aligncenter" src="https://lh4.googleusercontent.com/9X828Aj41raidhKpZ8DeFf6yCGPq4cjYaPRLYulQ2TQsMMB5SL0Y-5OODJrnbxOMK_oEO8ydMDbs437ILLeZLI2238qZ4QcJrZreOrCc5qTDgziBQapkGM5hwCABuxdT2w" alt="" width="450" height="181" /><br />
</strong></strong></p>
<p dir="ltr">What we can alternatively do is to pass it as a regular filter in the SUBQUERY form:</p>
<p><strong><strong><img class="aligncenter" src="https://lh3.googleusercontent.com/-I5348EB3deCxdFYn3RIOaMYLMnOqxvchX_ZtCXFEohcU1bTtYo_vOQ8WBPifMHbZwh7ikuzHaWEUhjxidt-8-6RE1reQX2utSpOR7h4JQw2f2fkaLaisKbXRE-87YjQkw" alt="" width="256" height="199" /><br />
</strong></strong></p>
<p><span style="font-size: small;"><span style="font-family: Consolas;"><span style="color: #000080;">DS.DAY_DATE &gt; (</span><span style="color: #008080;">SELECT</span><span style="color: #000080;"> to_date(</span><span style="color: #008080;">value</span><span style="color: #000080;">,</span><span style="color: #0000ff;">&#8216;YYYY-MM-DD&#8217;</span><span style="color: #000080;">) </span><span style="color: #008080;">FROM</span><span style="color: #000080;"> EDW.C_PARAMETER m </span><span style="color: #008080;">WHERE</span><span style="color: #000080;"> </span><span style="color: #008080;">KEY</span><span style="color: #000080;">=</span><span style="color: #0000ff;">&#8216;LAST_PROGRESS_DATE&#8217;</span><span style="color: #000080;">)</span></span></span></p>
<p dir="ltr"><span style="font-size: 13px;">It doesn’t improve it a bit. Still the INDEX RANGE SCAN is performed.<br />
</span><span style="font-size: 13px;">Both queries take between 40minutes to 1hour.</span></p>
<p><span style="font-size: 13px;">I can almost hear you shouting “Why don’t you use an ODI variable for it?” and you’re damn right, this would solve the problem.<br />
</span><span style="font-size: 13px;">When static value is used the query filter</span></p>
<p><span style="font-family: Consolas; color: #000080; font-size: small;">DS.DAY_DATE &gt; #V_LAST_PROGRESS_DATE</span></p>
<p dir="ltr">changes the plan to simply do the FULL TABLE scan which it should do in the first place;</p>
<p><strong><strong><img class="aligncenter" src="https://lh3.googleusercontent.com/TFcl6kBkhqBTnhfiebGIyreouKMx9c3aZYNpoL9yt-gI4Hj-I89xoIty4D2ZxD114ixXxR6F-PwE7czbvtQJkUHdN6SWOcNMP93HODtaP7-kfai_RFWBR33BJI3sS0JdGQ" alt="" width="347" height="54" /><br />
</strong></strong></p>
<p dir="ltr">Using an ODI variable however has also some downsides.<br />
<span style="font-size: 13px;">Each parameter introduces an overhead of dedicated ODI variable. This in practice translates to wrapping interface in the Package with separate declaration and separate refresh step.<br />
</span><span style="font-size: 13px;">Very often such parameters would use the same source for it but it still requires separate refresh definition. What I have in mind here is the elegant solution seen in OBIEE where variables are just different columns which can then share the same execution block.<br />
</span><span style="font-size: 13px;">Another thing is that with the complex logic the number of parameters usually grows fast which simply makes it difficult to manage.<br />
</span><span style="font-size: 13px;">Last but not least is the fact that it makes debugging difficult. Variables by default are not seen in the operator.</span></p>
<p dir="ltr">This can make it even harder to find out what’s happened on Production at some point in time when log is the only thing you left with.</p>
<p dir="ltr">I said ‘by default’ as there are ways to achive it. Prior to ODI version 11.1.1.6 the variable could be only printed using tricks like throwing and ignoring exceptions or switching history for variable, neither one elegant. From that version onwards there’s variable tracking feature but again as this requires running code with log level higher than 6 something not enabled by default, especially in production environment.</p>
<p><span style="font-size: 13px;">It turns out that with a bit of Java BeanShell scripting such parameter values can be sourced in a run-time from the database and substituted in the right place just before the query runs.</span></p>
<p><span style="font-size: 13px;">To make the code reusable we will wrap the Java BeanShell code into the function with the syntax defined as</span></p>
<p><span style="font-family: Consolas; color: #000080; font-size: small;">DS.DAY_DATE &gt; #V_LAST_PROGRESS_DATE</span></p>
<p><img class="aligncenter" src="https://lh5.googleusercontent.com/vDiCSuCfIXI9qJ-gQ435m_Qe8f7fM1AusGh9uQo0WVCARrt3WAqMSOxoajscYry2yd6wy57TDCAAOQsKQdCDWlAYtDhZJ2KfyW6Vyqr-BMWzkTY0zlQI4YFCzQ" alt="" width="260" height="175" /></p>
<p dir="ltr">The first parameter $(SQL) would just specify a full text of the query to return the parameter value. This is the equivalent of ODI Variable refresh SQL text.<br />
<span style="font-size: 13px;">The second one, $(AT) would specify which connection that refresh statement should be executed at. It should only take the values either &#8220;DEST&#8221;, &#8220;SRC&#8221; or &#8220;WORKREP&#8221;. Yes, it’s possible to get runtime repository values too!<br />
</span><span style="font-size: 13px;">The “SRC” might be very useful when “Command on Source/Command on Target” is used or simply when some different than Target schema is to be used for getting parameter value.</span></p>
<p dir="ltr">The implementation goes as following:</p>
<p><span style="font-family: Courier New; color: #ff0000; font-size: small;">&lt;?<br />
</span><span style="font-size: small;"><span style="font-family: Courier New;">java.sql.Connection targConnection <span style="color: #8000ff;">=</span> odiRef.getJDBCConnection<span style="color: #8000ff;">(</span><span style="color: #808080;">&#8220;$(AT)&#8221;</span><span style="color: #8000ff;">);</span></span></span><span style="font-size: small;"><span style="font-family: Courier New;"><br />
java.sql.Statement s <span style="color: #8000ff;">=</span> targConnection.createStatement<span style="color: #8000ff;">();</span></span></span><span style="font-size: small;"><span style="font-family: Courier New;"><strong><span style="color: #0000ff;"><br />
String</span></strong> query<span style="color: #8000ff;">=</span><span style="color: #808080;">&#8220;$(SQL)&#8221;</span><span style="color: #8000ff;">;</span></span></span><span style="font-size: small;"><span style="font-family: Courier New;"><br />
java.sql.ResultSet rs <span style="color: #8000ff;">=</span> s.executeQuery<span style="color: #8000ff;">(</span>query<span style="color: #8000ff;">);</span><br />
</span></span><span style="font-size: small;"><span style="font-family: Courier New;"><strong><span style="color: #0000ff;">if</span></strong> <span style="color: #8000ff;">(</span>rs.next<span style="color: #8000ff;">())<br />
</span></span></span><span style="font-size: small;"><span style="font-family: Courier New;">     out.println<span style="color: #8000ff;">(</span>rs.getString<span style="color: #8000ff;">(</span><span style="color: #ff8000;">1</span><span style="color: #8000ff;">));</span><br />
</span></span><strong><span style="font-family: Courier New; color: #0000ff; font-size: small;">else<br />
</span></strong><span style="font-size: small;"><span style="font-family: Courier New;">     throw <strong><span style="color: #0000ff;">new</span></strong> Exception<span style="color: #8000ff;">(</span><span style="color: #808080;">&#8220;Query &#8220;</span><span style="color: #8000ff;">+</span>query<span style="color: #8000ff;">+</span><span style="color: #808080;">&#8221; in UDF failed.&#8221;</span><span style="color: #8000ff;">);</span><br />
</span></span><span style="font-size: small;"><span style="font-family: Courier New;">s.close<span style="color: #8000ff;">();<br />
</span></span></span><span style="font-family: Courier New; color: #ff0000; font-size: small;">?&gt;</span><strong><strong><br />
</strong></strong></p>
<p dir="ltr">Now the name for our function. As you can see from the screenshot above, it is different from the one in the syntax.<br />
<span style="font-size: 13px;">I didn’t mention it before but this is where another trick comes in.<br />
</span><span style="font-size: 13px;">We can actually make the second function parameter optional.</span></p>
<p dir="ltr">While this is directly possible in many programming languages it’s not in ODI and what we need to do here instead is to leverage another paradigm taken from programming world called function overloading.<br />
<span style="font-size: 13px;">This will be achieved by creating another function that takes one parameter and executes the original one passing it and hardcoding the second one.<br />
</span><span style="font-size: 13px;">The name used in the syntax for both will be the same but the syntax itself will be obviously different:</span></p>
<p><strong><strong></strong></strong> </p>
<table width="761" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="top" width="225">
<p align="center"><strong><span style="font-size: medium;">ODI function name</span></strong></p>
</td>
<td valign="top" width="272">
<p align="center"><strong><span style="font-size: medium;">ODI function syntax</span></strong></p>
</td>
<td valign="top" width="264">
<p align="center"><strong><span style="font-size: medium;">implementation</span></strong></p>
</td>
</tr>
<tr>
<td valign="top" width="225"><span style="font-size: medium;">SUBST_QUERY_RESULT_VAL_AT</span></td>
<td valign="top" width="272">SUBST_QUERY_RESULT_VAL($(SQL),$(AT))</td>
<td valign="top" width="264"><span style="font-size: medium;">does the heavy lifting</span></td>
</tr>
<tr>
<td valign="top" width="225"><span style="font-size: medium;">SUBST_QUERY_RESULT_VAL</span></td>
<td valign="top" width="272">SUBST_QUERY_RESULT_VAL($(SQL))</td>
<td valign="top" width="264"><span style="font-size: medium;">executes the function above:</span>SUBST_QUERY_RESULT_VAL($(SQL),DEST)</td>
</tr>
</tbody>
</table>
<div dir="ltr"> </div>
<p><span style="font-size: 13px;">The second’s function implementation simply calls the first one transparently passing the same SQL and defaulting the $(AT) parameter with DEST value:</span></p>
<p><span style="font-family: Calibri;">SUBST_QUERY_RESULT_VAL($(SQL),<strong>DEST</strong>)</span></p>
<p dir="ltr">Thanks to it, the user can specify the second parameter or skip it whereby the ‘DEST’ would be used instead.<br />
<span style="font-size: 13px;">ODI will analyze the function call format used in the Interface and based on that will substitute relevant function.</span></p>
<p dir="ltr">I should also mention here there’s an ODI bug that may prevent from linking to the  right function.<br />
<span style="font-size: 13px;">I discovered the order in which functions are created plays a role here (values of internal ODI Object IDs?).</span></p>
<p dir="ltr">This means if we create the the ‘wrapper’ one first, ODI will assume there’s a recurrence call even within the function even when the call doesn’t match the function syntax. It can be easily diagnosed by expanding and examining ‘uses’ contents under the function itself. The following indicates wrong recurrence:</p>
<p dir="ltr"><img class="aligncenter" src="https://lh3.googleusercontent.com/hOgGwUnJsTjCugmIrbbx18Hcj_mPgIPDuCBKcrP6qn_veEIPw8L-lRkmpJ-gPgFccqgnv8JG9lc9jnSTGGEIpBjKuiIJ1PYJzBKLSzk0t2chq2_m2XuWFqH88w" alt="" width="209" height="80" /></p>
<p dir="ltr">If you created the functions in the order as described in this post you should see the calls are resolved properly:</p>
<p dir="ltr"><img class="aligncenter" src="https://lh4.googleusercontent.com/UxWFzVHOnI7zg7MBZuZYdi1aYTOqQmoghEz0PhyG9xe8welBW0DGcvZX88pjvKj9zbcNv4r8FyWocUmvJulZQMq1fEVCmhR1j26IE9DxR_NHOKH3rcflCLboNA" alt="" width="209" height="80" /></p>
<p dir="ltr">Coming back to our use case, those functions then allow using the SQL queries directly in the interface. The SQL filter below:</p>
<p><span style="font-size: small;"><span style="font-family: Consolas;"><span style="color: #000080;">DS.DAY_DATE &gt; SUBST_QUERY_RESULT_VAL(</span><span style="color: #008080;">SELECT</span><span style="color: #000080;"> </span><span style="color: #0000ff;">&#8216;date&#8221;&#8217;</span><span style="color: #000080;">||</span><span style="color: #008080;">value</span><span style="color: #000080;">||</span><span style="color: #0000ff;">&#8221;&#8221;</span><span style="color: #000080;"> </span><span style="color: #008080;">FROM</span><span style="color: #000080;"> C_PARAMETER </span><span style="color: #008080;">WHERE</span><span style="color: #000080;"> </span><span style="color: #008080;">KEY</span><span style="color: #000080;">=</span><span style="color: #0000ff;">&#8216;LAST_PROGRESS_DATE&#8217;</span><span style="color: #000080;">)</span></span></span></p>
<p dir="ltr">will be substituted nicely with</p>
<p><span style="font-size: small;"><span style="font-family: Consolas;"><span style="color: #000080;">DS.DAY_DATE &gt; </span><span style="color: #008080;">date</span><span style="color: #0000ff;">&#8217;2013-01-13&#8242;</span></span></span></p>
<p><span style="font-size: 13px;">which in brings down the query time to less than 3 minutes.</span></p>
<p><span style="font-size: 13px;">It’s not everything, the source schema for parameter table doesn’t need to be hardcoded either!<br />
</span><span style="font-size: 13px;">A function with nested substitution API call would work in the same way:</span></p>
<p><span style="font-size: small;"><span style="font-family: Consolas;"><span style="color: #000080;">DS.DAY_DATE &gt; SUBST_QUERY_RESULT_VAL(</span><span style="color: #008080;">SELECT</span><span style="color: #000080;"> </span><span style="color: #0000ff;">&#8216;date&#8221;&#8217;</span><span style="color: #000080;">||</span><span style="color: #008080;">value</span><span style="color: #000080;">||</span><span style="color: #0000ff;">&#8221;&#8221;</span><span style="color: #000080;"> </span><span style="color: #008080;">FROM</span><span style="color: #000080;"> &#8221;+odiRef.getObjectName(&#8220;C_PARAMETER&#8221;)+&#8221; </span><span style="color: #008080;">WHERE</span><span style="color: #000080;"> </span><span style="color: #008080;">KEY</span><span style="color: #000080;">=</span><span style="color: #0000ff;">&#8216;LAST_PROGRESS_DATE&#8217;</span><span style="color: #000080;">)</span></span></span></p>
<p><span style="font-size: 13px;">Please note that this ODI function call has one limitation though – The SQL parameter has to be all expressed within one line, doesn’t matter how long.<br />
</span><span style="font-size: 13px;">This however, with yet another trick can be lifted too.<br />
</span><span style="font-size: 13px;">You can learn about it and plenty of other useful ODI scripting techniques at the training we will have available soon.</span></p>
<img src="http://www.business-intelligence-quotient.com/?ak_action=api_record_view&id=1831&type=feed" alt="" /><h3  class="related_post_title">Most Popular Posts</h3><ul class="related_post"><li>April 5, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=119" title="Query hints in OBIEE">Query hints in OBIEE</a><br /><small>I have recently come across a post on the OTN forums on how to use hints in OBIEE. OBIEE lets you sp...</small></li><li>October 12, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=340" title="ODI: Automating deployment of scenarios to production in Oracle Data Integrator">ODI: Automating deployment of scenarios to production in Oracle Data Integrator</a><br /><small>In this post I will show you how you can automatically deploy scenarios in ODI.

It is rather cumb...</small></li><li>March 12, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=103" title="Consuming a REST web service with Oracle">Consuming a REST web service with Oracle</a><br /><small>SOAP web services dominate in a SOA environment. However, there is a new kid on the block: REST. Thi...</small></li><li>November 19, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=546" title="ODI Snippets: OdiSqlUnload with header">ODI Snippets: OdiSqlUnload with header</a><br /><small>OdiSqlUnload is a handy tool to quickly dump the content of a table into a CSV file. This is a lot q...</small></li><li>November 17, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=539" title="ODI snippets: Purge Log and shrink space">ODI snippets: Purge Log and shrink space</a><br /><small>We all know that we should purge the ODI log on a regular basis. if we log everything or if we run n...</small></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.business-intelligence-quotient.com/?feed=rss2&#038;p=1831</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Endeca text enrichment. Entities extraction, sentiment analysis, and text tagging with Lexalytics customer defined lists. I love this one!</title>
		<link>http://www.business-intelligence-quotient.com/?p=1801</link>
		<comments>http://www.business-intelligence-quotient.com/?p=1801#comments</comments>
		<pubDate>Thu, 18 Apr 2013 21:18:53 +0000</pubDate>
		<dc:creator>Uli Bethke</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[clover etl]]></category>
		<category><![CDATA[entity extraction]]></category>
		<category><![CDATA[lexalytics]]></category>
		<category><![CDATA[OEID]]></category>
		<category><![CDATA[sentiment analysis]]></category>
		<category><![CDATA[text analytics]]></category>
		<category><![CDATA[text enrichment]]></category>
		<category><![CDATA[text mining]]></category>
		<category><![CDATA[text tagging]]></category>
		<category><![CDATA[web scraping]]></category>

		<guid isPermaLink="false">http://www.business-intelligence-quotient.com/?p=1801</guid>
		<description><![CDATA[One of the interesting options of Endeca is its integration with text...]]></description>
			<content:encoded><![CDATA[<p>One of the interesting options of Endeca is its integration with text mining software Lexalytics (licensed separately). Lexalytics offers many text analysis functions such as sentiment analysis, document collection analysis, named entity extraction, theme and context extraction, summarization, document classification etc. Endeca exposes some of this functionality via its text enrichment component in Clover ETL. It is worthwhile noting that not all of the text analytics functionality is exposed via text enrichment and of those features that are exposed only a limited number of methods of the Lexalytics API are exposed (more on that later). A great way of learning more about Lexalytics is to visit their <a href="http://www.lexalytics.com/" target="_blank">website</a>, <a href="http://dev.lexalytics.com/wiki/pmwiki.php" target="_blank">Wiki</a>, and <a href="http://www.lexalytics.com/lexablog" target="_blank">blog</a>. I will post some more stuff on text analytics and Lexalytics in particular in one of my next posts.</p>
<h3>Text tagging with Lexalytics</h3>
<p>In <a href="http://www.business-intelligence-quotient.com/?p=1774">my last post on Endeca </a>we were using the text tagger component to tag a list of 16K Irish IT job records with 30K skills extracted from LinkedIn. If you remember we saw some dreadful performance and also realised that the text tagger component is not multi-threaded and maxed out at 25% on a quad-core CPU. The text enrichment component also offers text tagging and based on the documentation is also multi-threaded. So my expectation is that the tagging process is a lot quicker. Apart from the skills tagging exercise we will also perform some entity extraction on the jobs data and focus on People, Companies, and Products.</p>
<p>In a first step we download Lexalytics from edelivery.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/lexalytics.png"><img class="alignnone size-full wp-image-1803" title="lexalytics" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/lexalytics.png" alt="" width="642" height="258" /></a></p>
<p>We then add the license file that comes with the download to the Lexalytics root directory. In my case E:\Program Files (x86)\Lexalytics</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_m41b8a532.png"><img class="alignnone size-large wp-image-1805" title="text enrichment_html_m41b8a532" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_m41b8a532-662x160.png" alt="" width="662" height="160" /></a></p>
<p>We then add the salience.properties file to our project. This configuration file sets the various properties that we can make us of, e.g which types of entities we want to extract. As you can see from the screenshot below we will extract entities of type Person, Company, Product, and List. The interesting entity is the List entity. Through the List entity we can specify our own custom lists to the Lexalytics Salience engine.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_791623ab.png"><img class="alignnone size-large wp-image-1806" title="text enrichment_html_791623ab" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_791623ab-662x583.png" alt="" width="662" height="583" /></a></p>
<p>Custom lists are made available to Lexalytics in the E:\Program Files (x86)\Lexalytics\data\user\salience\entities\lists folder as a tab separated <a href="http://dev.lexalytics.com/wiki/pmwiki.php?n=DataDir.CDLFiles">Customer Defined List</a> file, which contains various values and a label separated by Tab.</p>
<p>One big shortcoming of the Endeca text enrichment component is that it does not extract the label that can be defined in the customer defined list, e.g. The following entry has the tab separated label of Business Intelligence. The text enrichment component does not extract this even though this is exposed by the Lexalytics API. This also means that you can only define one customer defined list per text enrichment batch, as all of your CDLs will be dumped into the List field.</p>
<p>OBIEE, Cognos, Micro Strategy Busines Intelligence</p>
<p>Anyway, below is our tab separated custom list</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_m2fdd285f.png"><img class="alignnone size-full wp-image-1808" title="text enrichment_html_m2fdd285f" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_m2fdd285f.png" alt="" width="526" height="507" /></a></p>
<p>Next we add the location of the Lexalytics license file and the data folder as variables to our project workspace parameter file.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_m1ae8ebe4.jpg"><img class="alignnone size-large wp-image-1809" title="text enrichment_html_m1ae8ebe4" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_m1ae8ebe4-662x332.jpg" alt="" width="662" height="332" /></a></p>
<p>As in the previous post we read the scraped data of Irish IT jobs from a MySQL database. The number now stands at 21K. The data flow is a lot simpler than what we had to do with the text tagger.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_m2e11925.jpg"><img class="alignnone size-large wp-image-1810" title="text enrichment_html_m2e11925" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_m2e11925-662x216.jpg" alt="" width="662" height="216" /></a></p>
<p>We are now ready to configure our text enrichment component. It&#8217;s all pretty straightforward. We supply:</p>
<p><strong>Configuration file</strong>: This is the path to the salience properties file</p>
<p><strong>Input file</strong>: This is the field in our recordset that we want to extract entities from and use for tagging.</p>
<p><strong>Salience license file</strong>: Path to Lexalytics license file</p>
<p><strong>Salience data path</strong>: Path to Lexalytics data folder</p>
<p><strong>Number of thread</strong>s: Hoooraaaay! This component is multi-threaded. During my test runs it used 1 core and maxed out at 25% CPU for 1 thread, 2 cores and maxed out at 50% CPU for 2 threads and so on.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_m75111f35.jpg"><img class="alignnone size-full wp-image-1811" title="text enrichment_html_m75111f35" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_m75111f35.jpg" alt="" width="635" height="455" /></a></p>
<p>In a last step we have to define the metadata and add it to the edge of the graph.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_e6b2de6.jpg"><img class="alignnone size-full wp-image-1812" title="text enrichment_html_e6b2de6" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_e6b2de6.jpg" alt="" width="593" height="607" /></a></p>
<p>We are now ready to run the graph. If you read my last <a href="http://www.business-intelligence-quotient.com/?p=1774">post on text tagging</a> you will remember that tagging with the text tagger component took a whopping 12 hours to tag 16K records against 30K skills. With the text enrichment component it took 20 minutes to tag 21K records and on top of that we also extracted Person, Product, and Company entities and did a bit of sentiment analysis as well.</p>
<p>Here are some of the results</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_6b0992de.jpg"><img class="alignnone size-large wp-image-1813" title="text enrichment_html_6b0992de" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/text-enrichment_html_6b0992de-662x351.jpg" alt="" width="662" height="351" /></a></p>
<h3>Conclusion</h3>
<p><ul class="list square"></ul> <li>If you have Lexalytics licensed as part of your Endeca install use it for text tagging rather than the Text Tagger component, which is pretty&#8230;, well,  lame.</li> <li>Unlike the Text Tagger component the Text Enrichment component (thanks to the underlying Lexalytics salience engine) is fine piece of software engineering. Unlike the text tagger it is multi-threaded and increasing the number of threads to 4 increased my CPU usage to 100%. It processes the incoming records in batches and it was a joy to watch how it cleared out the memory properly after each batch.</li> <li>The text enrichment component only exposes a subset of the Lexalytics functionality. If you want to make use of the full potential of the Salience engine you need to write your own custom code.</li><li>The text enrichment component offers a lot of room for improvement (1) It does not expose the full feature set of Lexalytics (2) The implementation of CDLs should include Label extraction. If you want to make use of the full Lexalytics functionality you would need to write a bit of custom code, which looks pretty straightforward to me.</li> [/list_check]</p>
<p>In the next posts we will load the data into the MDEX engine and start our discovery process. I wonder what we will find out???</p>
<p>&nbsp;</p>
<img src="http://www.business-intelligence-quotient.com/?ak_action=api_record_view&id=1801&type=feed" alt="" /><h3  class="related_post_title"></br>Related posts</h3><ul class="related_post"><li>April 1, 2013 -- <a href="http://www.business-intelligence-quotient.com/?p=1774" title="Endeca text tagging: Tagging unstructured IT jobs data against a whitelist of LinkedIn skills">Endeca text tagging: Tagging unstructured IT jobs data against a whitelist of LinkedIn skills</a><br /><small>A couple of days ago I have started to look at Endeca. So far it looks like a great tool and I belie...</small></li><li>January 6, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=20" title="Competitive Business Intelligence: web scraping with Oracle.">Competitive Business Intelligence: web scraping with Oracle.</a><br /><small>In my opinion, one of the trends for Business Intelligence in 2009 (and the years to come) will be t...</small></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.business-intelligence-quotient.com/?feed=rss2&#038;p=1801</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Endeca text tagging: Tagging unstructured IT jobs data against a whitelist of LinkedIn skills</title>
		<link>http://www.business-intelligence-quotient.com/?p=1774</link>
		<comments>http://www.business-intelligence-quotient.com/?p=1774#comments</comments>
		<pubDate>Mon, 01 Apr 2013 14:44:22 +0000</pubDate>
		<dc:creator>Uli Bethke</dc:creator>
				<category><![CDATA[Clover ETL]]></category>
		<category><![CDATA[Endeca]]></category>
		<category><![CDATA[Lexalytics]]></category>
		<category><![CDATA[clover etl]]></category>
		<category><![CDATA[endeca]]></category>
		<category><![CDATA[lexalytics]]></category>
		<category><![CDATA[multi-value attribute]]></category>
		<category><![CDATA[oracle endeca]]></category>
		<category><![CDATA[text tagger]]></category>

		<guid isPermaLink="false">http://www.business-intelligence-quotient.com/?p=1774</guid>
		<description><![CDATA[A couple of days ago I have started to look at Endeca....]]></description>
			<content:encoded><![CDATA[<p>A couple of days ago I have started to look at Endeca. So far it looks like a great tool and I believe we will see and hear a lot more from it over the next couple of months and years.</p>
<p>I am currently still learning a lot and in the next couple of weeks I will document my progress in a couple of blog posts. In this first post we will tag some unstructured data and then create a multi value attribute, which is one of the great features of Endeca.</p>
<p>In this example we look at some Irish IT job offerings data that has been extracted from the web. One of the fields of this data set is a description field. We will tag this unstructured data with a whitelist of skills that were extracted from LinkedIn. There are 30K skills right now on LinkedIn, which resulted in some performance issues when using the text tagger in Clover ETL. More on that later</p>
<p>Irish IT jobs data set (about 16K records collected over the last 3 months).</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_m1672bfb0.jpg"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_m1672bfb0.jpg" alt="" title="Endeca_html_m1672bfb0" width="228" height="348" class="alignnone size-full wp-image-1776" /></a></p>
<p>LinkedIn skills data set</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_64191cc.jpg"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_64191cc-662x361.jpg" alt="" title="Endeca_html_64191cc" width="662" height="361" class="alignnone size-large wp-image-1778" /></a></p>
<p>The Irish jobs data sits on a MySQL server. The skills data set is in an Excel sheet. The end result of our ETL will look like this.</p>
<p>Note: You need to name the input fields SearchTerm and TagValue respectively. Any other value will throw an error when loading via the Text Tagger component.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_5efd6b48.jpg"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_5efd6b48-662x359.jpg" alt="" title="Endeca_html_5efd6b48" width="662" height="359" class="alignnone size-large wp-image-1779" /></a></p>
<p>We first add a connection to the MySQL database</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_m6fa7c936.jpg"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_m6fa7c936.jpg" alt="" title="Endeca_html_m6fa7c936" width="623" height="600" class="alignnone size-full wp-image-1781" /></a></p>
<p>Next we create a graph and add the Irish Jobs and LinkedIn metadata to it. </p>
<p>Note: A data flow/mapping in CloverETL is named graph.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_m73b3e851.jpg"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_m73b3e851-662x474.jpg" alt="" title="Endeca_html_m73b3e851" width="662" height="474" class="alignnone size-large wp-image-1782" /></a></p>
<p>And the LinkedIn metadata</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_4faba45d.jpg"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_4faba45d-662x215.jpg" alt="" title="Endeca_html_4faba45d" width="662" height="215" class="alignnone size-large wp-image-1783" /></a></p>
<p>Next we add a DB_INPUT_TABLE and an XLS_DataReader and configure them</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_m1936dbc21.jpg"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_m1936dbc21-662x342.jpg" alt="" title="Endeca_html_m1936dbc2" width="662" height="342" class="alignnone size-large wp-image-1784" /></a></p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_m245f714e.jpg"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_m245f714e-662x539.jpg" alt="" title="Endeca_html_m245f714e" width="662" height="539" class="alignnone size-large wp-image-1785" /></a></p>
<p>Next we add the Text Tagger – Whitelist component from the Discovery palette and connect the Irishjobs_IE input table and the XLSDataReader for the LinkedInSkills to it. The Text Tagger takes two parameters as input. The unstructured text field that needs to be tagged and the name of the output field. In our case the Source Field Name is Description and the Target Field Name is DescriptionSkills. We still need to set up the latter as Metadata in the next step.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_m4048b06e.jpg"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_m4048b06e.jpg" alt="" title="Endeca_html_m4048b06e" width="659" height="497" class="alignnone size-full wp-image-1786" /></a></p>
<p>Note: I have set the multi-assign delimiter to “,”. This will separate the tagged skills as a comma separated list. In the Endeca Server we can treat this then as a multi-value attribute.</p>
<p>Next we need to create the Metadata for the output from the Text Tagger and add the DescriptionSkills field to it. We do this duplicating the metadata from the irishjobs_ie input table and manually adding the field DescriptionSkills to it.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_371fe3ab.jpg"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_371fe3ab.jpg" alt="" title="Endeca_html_371fe3ab" width="540" height="481" class="alignnone size-full wp-image-1787" /></a></p>
<p>Next we add a Bulk Add/Replace Records component to the graph, connect the Text Tagger to it, and add the newly created metadata to it. In the properties of the  Bulk Add/Replace Records component we specifiy the Spec Attribute (unique key) and the multi-assign delimiter. In our case that is a “,” (as specified earlier in the text tagger. The multi-assign delimiter is used to split the chain of comma separated values. What I find strange here is that you need to define a delimiter for all of your attributes. I would really expect to specify this at the attribute level rather than the dataset level.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_b3eb455.jpg"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_b3eb455-662x496.jpg" alt="" title="Endeca_html_b3eb455" width="662" height="496" class="alignnone size-large wp-image-1788" /></a></p>
<h3>ETL Performance problems</h3>
<p>Once this is done we can run the ETL. When I first ran this with 30K records in the skills whitelist the whole thing was crawling. For the 16K records it took 12 hours. I noticed that Clover was only using one core of my quad-core CPU at a time (maxed out at 25% CPU usage). An indication to me that multi-threading is not implemented. Either in the Text Tagger component itself or in Clover. I had a look on the Clover website and it stated there that it is multi-threaded so my conclusion for the moment is that the Text Tagger component is not multi-threaded or that the Desktop version of Clover is not multi-threaded. Can anyone please shed some light on this?</p>
<p>I was then experimenting a bit. What I found was that splitting the whitelist file into multiple smaller ones and then sending the jobs data through the Text Tagger sausage machine improved performance significantly. What that means is that Text Tagger performance is not linear, i.e. doubling the number of whitelist records does more than double elapsed time for tagging.</p>
<p>Below you see how the split is implemented in Clover. This should give you an idea how this can be done. I am sure this can be implemented in a more elegant way using splitters and loops and stuff. The take away though is that in order to get the best performance you need to play around with your whitelist sizes. </p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_m1f252c26.jpg"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_m1f252c26-662x306.jpg" alt="" title="Endeca_html_m1f252c26" width="662" height="306" class="alignnone size-large wp-image-1789" /></a></p>
<p>Note: The Reformat component is used to concatenate the resulting skills output fields from the Text Tagger components.</p>
<p>The result for 200 sample jobs for a subset of the skills (letters A-E) is as follows.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_3e10bc4b.jpg"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/04/Endeca_html_3e10bc4b-662x324.jpg" alt="" title="Endeca_html_3e10bc4b" width="662" height="324" class="alignnone size-large wp-image-1790" /></a></p>
<img src="http://www.business-intelligence-quotient.com/?ak_action=api_record_view&id=1774&type=feed" alt="" /><h3  class="related_post_title"></br>Related posts</h3><ul class="related_post"><li>April 18, 2013 -- <a href="http://www.business-intelligence-quotient.com/?p=1801" title="Endeca text enrichment. Entities extraction, sentiment analysis, and text tagging with Lexalytics customer defined lists. I love this one!">Endeca text enrichment. Entities extraction, sentiment analysis, and text tagging with Lexalytics customer defined lists. I love this one!</a><br /><small>One of the interesting options of Endeca is its integration with text mining software Lexalytics (li...</small></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.business-intelligence-quotient.com/?feed=rss2&#038;p=1774</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Oracle User Group Dublin, 12 March 2013. It&#8217;s FREE.</title>
		<link>http://www.business-intelligence-quotient.com/?p=1769</link>
		<comments>http://www.business-intelligence-quotient.com/?p=1769#comments</comments>
		<pubDate>Thu, 14 Feb 2013 17:51:38 +0000</pubDate>
		<dc:creator>Uli Bethke</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.business-intelligence-quotient.com/?p=1769</guid>
		<description><![CDATA[The annual Oracle User Group meeting in Dublin is this year on...]]></description>
			<content:encoded><![CDATA[<p>The annual Oracle User Group meeting in Dublin is this year on a special day. 12th of March. That&#8217;s my birthday.</p>
<p>The <a target="_blank" href="http://www.ukoug.org/2013-events/oug-ireland-2013/agenda/">agenda</a> is live now. Unfortunately, there is only one data warehouse/business intelligence stream this year. A lot of interesting presentations had to be left out.</p>
<p>I will present with Maciek Kocon on &#8220;Oracle Data Integrator 11g Best Practices. Busting your performance, deployment, and scheduling headaches&#8221;.</p>
<p>Other presentations include Mark Rittman on deploying OBIEE in the enterprise. Peak Indicators will be there to present on the concept and case study of a BI Competency Centre (BICC), and there will be a presentation on best practices in migrating from OWB to ODI.</p>
<p>Oracle themselves also have a stream on the 12c database.</p>
<p>If you are not interested in any of the above you may be interested in the free lunch.</p>
<p><a target="_blank" href="http://www.ukoug.org/2013-events/oug-ireland-2013/registration/">Register now</a>. Only a few places remain.</p>
<p>See you there!</p>
<img src="http://www.business-intelligence-quotient.com/?ak_action=api_record_view&id=1769&type=feed" alt="" /><h3  class="related_post_title">Most Popular Posts</h3><ul class="related_post"><li>April 5, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=119" title="Query hints in OBIEE">Query hints in OBIEE</a><br /><small>I have recently come across a post on the OTN forums on how to use hints in OBIEE. OBIEE lets you sp...</small></li><li>October 12, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=340" title="ODI: Automating deployment of scenarios to production in Oracle Data Integrator">ODI: Automating deployment of scenarios to production in Oracle Data Integrator</a><br /><small>In this post I will show you how you can automatically deploy scenarios in ODI.

It is rather cumb...</small></li><li>March 12, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=103" title="Consuming a REST web service with Oracle">Consuming a REST web service with Oracle</a><br /><small>SOAP web services dominate in a SOA environment. However, there is a new kid on the block: REST. Thi...</small></li><li>November 19, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=546" title="ODI Snippets: OdiSqlUnload with header">ODI Snippets: OdiSqlUnload with header</a><br /><small>OdiSqlUnload is a handy tool to quickly dump the content of a table into a CSV file. This is a lot q...</small></li><li>November 17, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=539" title="ODI snippets: Purge Log and shrink space">ODI snippets: Purge Log and shrink space</a><br /><small>We all know that we should purge the ODI log on a regular basis. if we log everything or if we run n...</small></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.business-intelligence-quotient.com/?feed=rss2&#038;p=1769</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Extreme re-usability in ODI 11g (I can’t believe I am giving away this trick).</title>
		<link>http://www.business-intelligence-quotient.com/?p=1754</link>
		<comments>http://www.business-intelligence-quotient.com/?p=1754#comments</comments>
		<pubDate>Mon, 07 Jan 2013 18:17:04 +0000</pubDate>
		<dc:creator>Uli Bethke</dc:creator>
				<category><![CDATA[Oracle Data Integrator (ODI)]]></category>
		<category><![CDATA[ODI 11G]]></category>
		<category><![CDATA[odi re-usability]]></category>
		<category><![CDATA[odi user defined functions]]></category>
		<category><![CDATA[ODI user functions]]></category>

		<guid isPermaLink="false">http://www.business-intelligence-quotient.com/?p=1754</guid>
		<description><![CDATA[Another Christmas and a second baby under my belt it’s time to...]]></description>
			<content:encoded><![CDATA[<p>Another Christmas and a second baby under my belt it’s time to get back to blogging.</p>
<p>There were recently some good posts by <a href="https://blogs.oracle.com/dataintegration/entry/odi_11g_cleaning_control_characters">David Allan</a> and <a href="http://gurcanorhan.wordpress.com/2012/12/05/adding-functions-to-odi/">Gurcan Orhan</a> on the power of ODI functions. David mentions correctly that ODI functions are the most underrated feature in ODI. Whenever you think of re-usability in ODI think of user functions. Functions can be used anywhere in ODI where you need to write something once and apply it many times. This is not limited to using functions inside interfaces to load columns or the use of wrapping and parameterizing common functionality. You could just write a snippet of SQL, e.g. a commonly used filter in a WHERE clause as a function and reuse it many times. The nice thing about functions is that you can use substitution method API calls in a function, use Java or the ODI tools.</p>
<h4>Use case for re-use of user functions</h4>
<p>One of the things that have puzzled me about ODI and Knowledge Modules is that some of the steps in the KMs are repeated and re-used over and over again without some central placeholder. Why not write the step once and re-use it many times across the Knowledge Modules? This is exactly what I will show you. We will take table stats gathering as an example. One of the steps in Knowledge Modules is to gather table stats once the target table has been loaded. Why not create a user function that gathers table stats on a target table and takes the estimate percent size as a parameter?</p>
<p>In a first step let’s create the function. As a recommendation I would suggest to prefix your functions with a convention. In a first implementation I had GATHER_TABLE_STATS for the syntax, which wreaked havoc with any KMs that are using the Oracle GATHER_TABLE_STATS procedure in package dbms_stats.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/01/uf1.jpg"><img class="alignnone size-large wp-image-1755" title="uf1" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/01/uf1-528x215.jpg" alt="" width="528" height="215" /></a></p>
<p>And the implementation</p>
<pre class="brush: sql;">
BEGIN

dbms_stats.gather_table_stats ( ownname =&gt; '&lt;%=odiRef.getInfo( "DEST_SCHEMA" )%&gt;', tabname =&gt; '&lt;%=odiRef.getTargetTable("RES_NAME")%&gt;', degree =&gt; DBMS_STATS.AUTO_DEGREE, estimate_percent =&gt; $(sample_size), cascade =&gt; TRUE  ) ;

END;
</pre>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/01/uf2.jpg"><img class="alignnone size-medium wp-image-1756" title="uf2" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/01/uf2-300x139.jpg" alt="" width="300" height="139" /></a></p>
<p>Next we will use the function as a step in a (global) Knowledge Module and pass in 10 as a parameter for the estimate_percent part of the stats gathering piece. In this particular case I have modified the IKM SQL Control Append.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/01/uf3.jpg"><img class="alignnone size-full wp-image-1758" title="uf3" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/01/uf3.jpg" alt="" width="469" height="505" /></a></p>
<p>Then we create and execute an interface that uses this IKM</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/01/uf4.jpg"><img class="alignnone size-medium wp-image-1759" title="uf4" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2013/01/uf4-300x80.jpg" alt="" width="300" height="80" /></a></p>
<p>As you can see the function was substituted at runtime and stats were gathered on the target table.</p>
<p>This is just one example where you can benefit from user function re-usability. Be creative and think out of the box and you will see user function written over everything.</p>
<img src="http://www.business-intelligence-quotient.com/?ak_action=api_record_view&id=1754&type=feed" alt="" /><h3  class="related_post_title"></br>Related posts</h3><ul class="related_post"><li>December 12, 2012 -- <a href="http://www.business-intelligence-quotient.com/?p=1739" title="How you can launch an ODI scenario through a web service call?">How you can launch an ODI scenario through a web service call?</a><br /><small>ODI and Jetty
The ODI 11g standalone agent now ships with its own lightweight application server (J...</small></li><li>October 30, 2012 -- <a href="http://www.business-intelligence-quotient.com/?p=1692" title="ODI Snippets: What is the Optimization Context in ODI?">ODI Snippets: What is the Optimization Context in ODI?</a><br /><small>There are a lot of confusing messages out there on what the Optimization Context in ODI is used for....</small></li><li>October 22, 2012 -- <a href="http://www.business-intelligence-quotient.com/?p=1678" title="How to query a whole schema or even database?! This tip will save you hours and hours of boring work.">How to query a whole schema or even database?! This tip will save you hours and hours of boring work.</a><br /><small>I really like this tip especially its simplicity. It has saved me hours and hours of mind numbing wo...</small></li><li>October 3, 2012 -- <a href="http://www.business-intelligence-quotient.com/?p=1617" title="Best practice of organizing interfaces and data stores into projects and models in ODI">Best practice of organizing interfaces and data stores into projects and models in ODI</a><br /><small>Have you ever wondered what the best way is to structure your objects in ODI into projects? Look no ...</small></li><li>September 27, 2012 -- <a href="http://www.business-intelligence-quotient.com/?p=1610" title="ODI snippets: Generating ANSI compliant Joins in Oracle">ODI snippets: Generating ANSI compliant Joins in Oracle</a><br /><small>It's great to see that the Oracle technology in ODI 11g now supports ANSI compliant JOINS. 

Howev...</small></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.business-intelligence-quotient.com/?feed=rss2&#038;p=1754</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How you can launch an ODI scenario through a web service call?</title>
		<link>http://www.business-intelligence-quotient.com/?p=1739</link>
		<comments>http://www.business-intelligence-quotient.com/?p=1739#comments</comments>
		<pubDate>Wed, 12 Dec 2012 18:10:09 +0000</pubDate>
		<dc:creator>Uli Bethke</dc:creator>
				<category><![CDATA[Oracle Data Integrator (ODI)]]></category>
		<category><![CDATA[ODI 11G]]></category>
		<category><![CDATA[odi asynchronous web service]]></category>
		<category><![CDATA[odi jetty]]></category>

		<guid isPermaLink="false">http://www.business-intelligence-quotient.com/?p=1739</guid>
		<description><![CDATA[ODI and Jetty The ODI 11g standalone agent now ships with its...]]></description>
			<content:encoded><![CDATA[<h4>ODI and Jetty</h4>
<p>The ODI 11g standalone agent now ships with its own lightweight application server (<a href="http://jetty.codehaus.org/jetty/">Jetty</a>). The main reason this was included is to make it easier to execute scenarios via web service calls. In the past this was quite painful as you needed a separate application server (OC4J). The other limitation was that it was difficult (read work around) to implement asynchronous web service calls. Luckily, this has all changed with ODI 11g and Jetty. However, I don&#8217;t believe that you can run the ODI console in Jetty, which is unfortunate.</p>
<h4>Asynchronous web service calls</h4>
<p>The WSDL can be found at http://&lt;standaloneagentname&gt;:&lt;port&gt;/oraclediagent/OdiInvoke?wsdl</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/12/scen_web_service.png"><img class="alignnone size-large wp-image-1742" title="scen_web_service" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/12/scen_web_service-662x665.png" alt="" width="662" height="665" /></a></p>
<p>&nbsp;</p>
<p>We can call the web service methods from any SOAP Client, e.g. the OdiInvokeWebService tool built into ODI.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/12/scen_web_service2.png"><img class="alignnone size-large wp-image-1741" title="scen_web_service2" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/12/scen_web_service2-662x436.png" alt="" width="662" height="436" /></a></p>
<p>We need to provide our login, the work repository for execution, the name of the scenario, its version, and the context. You can also specify if you want the scenario to be executed synchronously or asynchronously. If you set Synchronous to false then control will be handed back to the client immediately. If you set it to true it will execute and then return control. In asynchronous scenarios you can use the session ID from the response file and the getSessionStatus method to return the status of your scenario execution.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/12/scen_web_service3.png"><img class="alignnone size-full wp-image-1740" title="scen_web_service3" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/12/scen_web_service3.png" alt="" width="580" height="326" /></a></p>
<p>The other thing you have to be aware of is that when you launch a scenario through a web service call it will fork out a new agent based on your odiparams.bat. You need to plan for the extra memory used up.</p>
<p>You can now easily orchestrate your process flows in BEPL or launch them from OBIEE.</p>
<img src="http://www.business-intelligence-quotient.com/?ak_action=api_record_view&id=1739&type=feed" alt="" /><h3  class="related_post_title"></br>Related posts</h3><ul class="related_post"><li>January 7, 2013 -- <a href="http://www.business-intelligence-quotient.com/?p=1754" title="Extreme re-usability in ODI 11g (I can’t believe I am giving away this trick).">Extreme re-usability in ODI 11g (I can’t believe I am giving away this trick).</a><br /><small>Another Christmas and a second baby under my belt it’s time to get back to blogging.

There were r...</small></li><li>October 30, 2012 -- <a href="http://www.business-intelligence-quotient.com/?p=1692" title="ODI Snippets: What is the Optimization Context in ODI?">ODI Snippets: What is the Optimization Context in ODI?</a><br /><small>There are a lot of confusing messages out there on what the Optimization Context in ODI is used for....</small></li><li>October 22, 2012 -- <a href="http://www.business-intelligence-quotient.com/?p=1678" title="How to query a whole schema or even database?! This tip will save you hours and hours of boring work.">How to query a whole schema or even database?! This tip will save you hours and hours of boring work.</a><br /><small>I really like this tip especially its simplicity. It has saved me hours and hours of mind numbing wo...</small></li><li>October 3, 2012 -- <a href="http://www.business-intelligence-quotient.com/?p=1617" title="Best practice of organizing interfaces and data stores into projects and models in ODI">Best practice of organizing interfaces and data stores into projects and models in ODI</a><br /><small>Have you ever wondered what the best way is to structure your objects in ODI into projects? Look no ...</small></li><li>September 27, 2012 -- <a href="http://www.business-intelligence-quotient.com/?p=1610" title="ODI snippets: Generating ANSI compliant Joins in Oracle">ODI snippets: Generating ANSI compliant Joins in Oracle</a><br /><small>It's great to see that the Oracle technology in ODI 11g now supports ANSI compliant JOINS. 

Howev...</small></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.business-intelligence-quotient.com/?feed=rss2&#038;p=1739</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Exadata, Exalytics, SAP HANA and the multi billion dollar question.</title>
		<link>http://www.business-intelligence-quotient.com/?p=1727</link>
		<comments>http://www.business-intelligence-quotient.com/?p=1727#comments</comments>
		<pubDate>Tue, 27 Nov 2012 22:51:32 +0000</pubDate>
		<dc:creator>Uli Bethke</dc:creator>
				<category><![CDATA[Business Intelligence]]></category>
		<category><![CDATA[Data Warehouse]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[exadata]]></category>
		<category><![CDATA[exadata vs sap hana]]></category>
		<category><![CDATA[exalytics]]></category>
		<category><![CDATA[exalytics vs sap hana]]></category>
		<category><![CDATA[Google F1]]></category>
		<category><![CDATA[IMDB]]></category>
		<category><![CDATA[SAP HANA]]></category>

		<guid isPermaLink="false">http://www.business-intelligence-quotient.com/?p=1727</guid>
		<description><![CDATA[Recently there has been a lot of noise around in memory databases...]]></description>
			<content:encoded><![CDATA[<p>Recently there has been a lot of noise around in memory databases and how Exadata, Exalytics and SAP HANA compare to each other. Here are my two cents on the debate.</p>
<h4>Why you can&#8217;t compare Exalytics to SAP Hana</h4>
<p>It is the vision of SAP Hana to be used for both OLTP and analytics. As the name already suggests Exalytics just caters for analytics. Exalytics needs to be loaded from the data warehouse or transactional systems. Not needed for Hana. Everything already sits in memory. While Exalytics is near near realtime. Hana is realtime. However, currently there are not too many OLTP applications running on Hana. The problem is that applications need to be adapted or rewritten to make full use of HANA&#8217;s new architecture.This seems about to change. SAP has recently released a service pack for HANA that will allow it to do just that. However, the claim of being able to run OLTP and Analytics in the same in memory database remains somewhat unproven.</p>
<h4>Why you can&#8217;t compare Exadata to SAP Hana</h4>
<p>Exadata V3 now ships with 4 TB of RAM. Contrary to the claims of Oracle this does not make it an in-memory database. It lacks two important features:</p>
<p>- Most of the data still sits on disk. Mostly SSD. Still disk<br />
- It lacks the optimized algorithms and design features (in memory indexes etc.) that have specifically been designed for in memory access.</p>
<h4>How does HANA compare to Exadata/Exalytics then?</h4>
<p>Well, it doesn&#8217;t. Oracle (or anyone else for that matter) still has to come up with a product that can be compared to HANA.</p>
<h4>Use cases of SAP HANA</h4>
<p>The number 1 use case for SAP HANA is for realtime operational business intelligence. True realtime BI now seems a distinct possibility. In this use case HANA represents the Interactive Sector as defined by Inmon et al. in their <a href="http://www.business-intelligence-quotient.com/?p=13">DW 2.0 book</a>.</p>
<p>The other use case is similar to what Exalytics is used for. A performance booster for the data warehouse. In this scenario we load or replicate data into the in-memory database either directly from our OLTP systems or the data warehouse. This is what we have predominantly seen HANA being used for so far. However, this falls well short of the vision and long term strategy, namely to change the way we do databases.</p>
<p>The third use case of course and the end game for HANA is to run OLTP, data warehouse, and analytics all on HANA. Not very realistic at the moment. DRAM is still too costly.</p>
<h4>What happens next?</h4>
<p>This is the billion dollar question. <a href="http://www.dbms2.com" target="_blank">Curt Monash</a> thinks:</p>
<p>&#8220;Putting all that together, the analytic case for SAP HANA seems decently substantiated, there are years of experience with the technology and its antecedents, and column stores (including in-memory) are well-established for analytics via multiple vendors. The OLTP case for HANA, however, remains largely unproven. It will be interesting to see how it plays out.&#8221;</p>
<p>It will indeed be interesting to see how this plays out. SAP are currently heavily promoting HANA. There is a <a href="http://scn.sap.com/docs/DOC-28294">developer license</a> available. You can rent an instance on AWS. SAP are pushing it hard for start-ups. I am sure that it will replace Oracle in many SAP implementations as the underlying database. It remains to be seen, however, if it can eat into the wider database market (the ultimate SAP objective). The other interesting question is: when will Oracle come up with a product that can compete head on with HANA? I believe there is plenty of time. The game hasn&#8217;t really started yet.</p>
<p>In the meantime Microsoft have also announced an in memory database named Hekaton for release in 2014/15. It seems to be for OLTP only and from what I read a bit of a joke. Interesting times indeed though.</p>
<h4>The wider picture and Google</h4>
<p>At the moment we are seeing some tectonic shifts in the technology space that we haven&#8217;t seen in a generation. New technologies like Hadoop, Impala, IMDBs, NoSQL, Cloud etc are emerging that can handle ever bigger data at an ever faster speed. These innovations will have knock on effects on the way we architect information systems and on enterprise architecture in general. I even believe that they will ultimately change the way we do business. Unknown to many, a lot of these innovations are pioneered by Google. Papers on <a href="http://research.google.com/archive/mapreduce.html" target="_blank">MapReduce  </a>and the Google File System kicked off Hadoop. Google <a href="http://static.googleusercontent.com/external_content/untrusted_dlcp/research.google.com/en//archive/bigtable-osdi06.pdf" target="_blank">BigTable</a>  inspired a lot of the NoSQL databases we have seen recently. You may have heard of Impala from Cloudera. Again a brainchild of Google. Based on <a href="http://research.google.com/archive/spanner.html" target="_blank">Google Spanner</a> and probably more so their in-house RDBMS <a href="http://research.google.com/pubs/pub38125.html" target="_blank">F1</a>.</p>
<p>I would expect more innovation to come from that corner. After all Google is at the epicentre of the Big Data problem. They already have their own offering named <a href="https://developers.google.com/bigquery/">BigQuery</a>, which recently left the Beta phase. Doesn&#8217;t look like much right now but I expect them to up their game.</p>
<p>Of course you can ignore those trends but you do so at your own peril.</p>
<p>If you want to find out more about IMDBs and SAP Hana I recommend to read <a href="http://www.amazon.com/gp/product/3642295746/ref=as_li_ss_tl?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=3642295746&amp;linkCode=as2&amp;tag=oracledi-20">In-Memory Data Management: Technology and Applications</a> by Hasso Plattner, one of the co-founders of SAP.</p>
<img src="http://www.business-intelligence-quotient.com/?ak_action=api_record_view&id=1727&type=feed" alt="" /><h3  class="related_post_title"></br>Related posts</h3><ul class="related_post"><li>August 13, 2010 -- <a href="http://www.business-intelligence-quotient.com/?p=1030" title="Comparing Exadata and Netezza TwinFin">Comparing Exadata and Netezza TwinFin</a><br /><small>Comparison between Exadata and Netezza Twin Fin. Ok, it comes from Netezza and as such is biased, bu...</small></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.business-intelligence-quotient.com/?feed=rss2&#038;p=1727</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Tricks with SQL: Beware of the Predicate in the Outer Join</title>
		<link>http://www.business-intelligence-quotient.com/?p=1714</link>
		<comments>http://www.business-intelligence-quotient.com/?p=1714#comments</comments>
		<pubDate>Wed, 21 Nov 2012 17:57:54 +0000</pubDate>
		<dc:creator>Uli Bethke</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[filter condition outer join]]></category>
		<category><![CDATA[filter outer join]]></category>
		<category><![CDATA[predicate outer join]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://www.business-intelligence-quotient.com/?p=1714</guid>
		<description><![CDATA[Today we will have a look what happens when we place a...]]></description>
			<content:encoded><![CDATA[<p>Today we will have a look what happens when we place a filter condition into an outer join. We will also have a look at how this compares to placing the filter condition into the WHERE clause. Finally we&#8217;ll have a look where this could be useful.</p>
<p>Let&#8217;s first create some sample data.</p>
<pre class="brush: sql;">
create table customer (
cust_id number,
cust_desc varchar2(50)
);

ALTER TABLE customer
add CONSTRAINT pk_customer PRIMARY KEY (cust_id);

create table customer_loc (
customer_loc_id NUMBER,
customer_id NUMBER,
customer_loc_desc VARCHAR2(50)
);

ALTER TABLE customer_loc
add CONSTRAINT pk_customer_loc PRIMARY KEY (customer_loc_id);

insert into customer values (1,'Gold');
insert into customer values (2,'Gold');
insert into customer values (3,'Silver');

insert into customer_loc values (1,1,'Dublin');
insert into customer_loc values (2,2,'Paris');
insert into customer_loc values (3,4,'Berlin');

commit;

analyze table customer compute statistics;
analyze table customer_loc compute statistics;</pre>
<p>Let&#8217;s run our first outer join query where we put the filter condition into the WHERE clause. All is as expected. The query just returns customer_id 1.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/11/sql1.png"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/11/sql1-662x491.png" alt="" title="sql1" width="662" height="491" class="alignnone size-large wp-image-1720" /></a></p>
<p>Now let&#8217;s run the same query, but we put the filter condition into the join. This may be different from what you may have expected. What happens is that the query returns all of the rows in the customer table and those rows of table customer_loc where the join condition is met, i.e. those rows where customer_id = 1.<br />
<a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/11/sql2.png"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/11/sql2-662x503.png" alt="" title="sql2" width="662" height="503" class="alignnone size-large wp-image-1722" /></a></p>
<p>Let&#8217;s verify what we have just seen with another query. This time we will put customer_id = 4 into the Join condition. There are no rows in table customer_loc that match this. As expected the query returns all rows for table customer but now rows for table customer_loc</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/11/sql3.png"><img src="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/11/sql3-662x534.png" alt="" title="sql3" width="662" height="534" class="alignnone size-large wp-image-1723" /></a></p>
<p>What could this be useful for? One use case would be some limited form of data densification whereby you need to return all of the tables in one table but only a subset of rows in another table. Typically this can only be done using some sort of subselect. An example:</p>
<p>The query below is run in the SH schema and returns all of the customers, but only those sales transactions that are larger than 1000 in sales_amount.</p>
<pre class="brush: sql;">
select a.cust_id,amount_sold
from customers a 
left outer join sales b on a.cust_id = b.cust_id and amount_sold > 1000;
</pre>
<img src="http://www.business-intelligence-quotient.com/?ak_action=api_record_view&id=1714&type=feed" alt="" /><h3  class="related_post_title"></br>Related posts</h3><ul class="related_post"><li>August 9, 2008 -- <a href="http://www.business-intelligence-quotient.com/?p=10" title="CSV to Rows">CSV to Rows</a><br /><small>I recently needed to convert a comma separated list of values in a table column to a column where ea...</small></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.business-intelligence-quotient.com/?feed=rss2&#038;p=1714</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Making use of ODI Flexfields to meet requirements</title>
		<link>http://www.business-intelligence-quotient.com/?p=1702</link>
		<comments>http://www.business-intelligence-quotient.com/?p=1702#comments</comments>
		<pubDate>Mon, 12 Nov 2012 18:12:38 +0000</pubDate>
		<dc:creator>Uli Bethke</dc:creator>
				<category><![CDATA[Oracle Data Integrator (ODI)]]></category>
		<category><![CDATA[ODI Flexfields]]></category>

		<guid isPermaLink="false">http://www.business-intelligence-quotient.com/?p=1702</guid>
		<description><![CDATA[What are ODI Flexfields? In ODI you can create user-defined fields on...]]></description>
			<content:encoded><![CDATA[<h4>What are ODI Flexfields?</h4>
<p>In ODI you can create user-defined fields on certain objects. You can think of these fields as additional attributes for certain objects. At design time you populate these attributes with values that are then used at runtime, e.g. by a Knowledge Module. There are various Flexfields defined out of the box for very specific requirements, e.g. there are Flexfields defined on the Datastore object for SAP and HIVE data integration tasks.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/11/flexfield1.png"><img class="alignnone size-full wp-image-1706" title="flexfield1" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/11/flexfield1.png" alt="" width="606" height="157" /></a></p>
<h4>Where do you create them?</h4>
<p>You create Flexfields in the Security module under the Objects accordion. You can’t create Flexfields for all of the objects. While you can create a Flexfield for an Interface you can’t create a Flexfield for an Interface Target Table.<br />
Once you have created the Flexfield you can then populate it with values in Designer.<br />
An example<br />
You have a requirement to log errors to an error table using a CKM. Based on the severity of the error you want to allow records through to your target table. DQ checks that result in minor errors are logged in the error table and go through to the target. Records with more sever issues only go to the error table and do not end up in the target table.<br />
In a first step we need to define a Numeric type Flexfield on the Condition object. We name this field Passthrough</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/11/flexfield2.png"><img class="alignnone size-full wp-image-1705" title="flexfield2" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/11/flexfield2.png" alt="" width="606" height="193" /></a></p>
<p>When you create your DQ Condition in Designer you can then set the value for the Flexfield. The value 1 will allow the record to go through to the target table even if there is a violation of the DQ check.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/11/flexfield3.png"><img class="alignnone size-full wp-image-1704" title="flexfield3" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/11/flexfield3.png" alt="" width="606" height="265" /></a></p>
<p>In a next step we need to write some code in our CKM to make use of the Flexfield and implement the above logic.</p>
<p>We store the value of the Flexfield in a variable passthrough and flag all of the records with the passthrough value.</p>
<p>&lt;? passthrough=&#8221;&lt;%=odiRef.getFlexFieldValue(&#8220;&#8221; + odiRef.getCK(&#8220;ID&#8221;) + &#8220;&#8221;,&#8221;2500&#8243;,&#8221;PASSTHROUGH_COND&#8221;)%&gt;&#8221;.replaceAll(&#8220;&#8216;&#8221;,&#8221;&#8221;&#8221;&#8221;); ?&gt;</p>
<p>As you can see from the figure below, 2500 is the internal ID of object Condition in the ODI repository.</p>
<p><a href="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/11/flexfield4.png"><img class="alignnone size-full wp-image-1703" title="flexfield4" src="http://www.business-intelligence-quotient.com/wp-content/uploads/2012/11/flexfield4.png" alt="" width="381" height="257" /></a></p>
<img src="http://www.business-intelligence-quotient.com/?ak_action=api_record_view&id=1702&type=feed" alt="" /><h3  class="related_post_title">Most Popular Posts</h3><ul class="related_post"><li>April 5, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=119" title="Query hints in OBIEE">Query hints in OBIEE</a><br /><small>I have recently come across a post on the OTN forums on how to use hints in OBIEE. OBIEE lets you sp...</small></li><li>October 12, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=340" title="ODI: Automating deployment of scenarios to production in Oracle Data Integrator">ODI: Automating deployment of scenarios to production in Oracle Data Integrator</a><br /><small>In this post I will show you how you can automatically deploy scenarios in ODI.

It is rather cumb...</small></li><li>March 12, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=103" title="Consuming a REST web service with Oracle">Consuming a REST web service with Oracle</a><br /><small>SOAP web services dominate in a SOA environment. However, there is a new kid on the block: REST. Thi...</small></li><li>November 19, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=546" title="ODI Snippets: OdiSqlUnload with header">ODI Snippets: OdiSqlUnload with header</a><br /><small>OdiSqlUnload is a handy tool to quickly dump the content of a table into a CSV file. This is a lot q...</small></li><li>November 17, 2009 -- <a href="http://www.business-intelligence-quotient.com/?p=539" title="ODI snippets: Purge Log and shrink space">ODI snippets: Purge Log and shrink space</a><br /><small>We all know that we should purge the ODI log on a regular basis. if we log everything or if we run n...</small></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.business-intelligence-quotient.com/?feed=rss2&#038;p=1702</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
