I had discussed a technique earlier (http://dreamingincrm.com/2015/05/31/performing-outer-join-in-advanced-find/) on how to use a plugin to intercept the RetrieveMultiple message and modify the fetchxml to facilitate outer join. The guys at Cobalt also have developed a full-fledged solution using the same technique called Intelligent Query
If you don’t want to use a plugin, because your are worried about performance or cannot install either of these solutions into an environment because of organisation policies, you can use this bookmarklet to do the outer join.
Code
var contentPanel = $('#crmContentPanel > iframe'); if (contentPanel && contentPanel.length > 0) { var targetFrame = contentPanel[0].contentWindow; targetFrame.ExecuteQuery(); var xml = targetFrame.$get("FetchXml").value; var isFetchModified = false; var xmlDoc = $.parseXML(xml), $xml = $(xmlDoc), outer = $xml.find("condition[operator=null]"); var mainFilter = $xml.has('entity > filter'); if (mainFilter.length === 0) $xml.find('entity').append('<filter></filter>'); $xml.find('link-entity').each(function (i, d) { var entity = $(d).attr('name'); var entityAlias = $(d).attr('alias'); var outerJoinCondition = $(d).find("condition[operator=null]"); if (entity + 'id' === outerJoinCondition.attr('attribute')) { $(d).attr('link-type', 'outer'); $xml.find('entity > filter').append('<condition entityname="' + entityAlias + '" attribute="' + entity + 'id" operator="null" />'); if (!isFetchModified) isFetchModified = true; } }); if (isFetchModified) { outer.remove(); targetFrame.$get("FetchXml", $get("resultRender")).value = '<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true">' + xmlDoc.documentElement.innerHTML + '</fetch>'; } targetFrame.changeArea(targetFrame.ResultsPage); targetFrame.$get('resultRender').submit(); } else { alert('Cannot locate Advanced Find Frame'); }
Bookmarket
Select the script below and drag it into your bookmarks bar into Chrome or IE.
javascript:var contentPanel=$('#crmContentPanel > iframe');if(contentPanel&&contentPanel.length>0){var targetFrame=contentPanel[0].contentWindow;targetFrame.ExecuteQuery();var xml=targetFrame.$get("FetchXml").value;var isFetchModified=false;var xmlDoc=$.parseXML(xml),$xml=$(xmlDoc),outer=$xml.find("condition[operator=null]");var mainFilter=$xml.has('entity > filter');if(mainFilter.length===0){$xml.find('entity').append('<filter></filter>');} $xml.find('link-entity').each(function(i,d){var entity=$(d).attr('name');var entityAlias=$(d).attr('alias');var outerJoinCondition=$(d).find("condition[operator=null]");if(entity+'id'===outerJoinCondition.attr('attribute')){$(d).attr('link-type','outer');$xml.find('entity > filter').append('<condition entityname="'+entityAlias+'" attribute="'+entity+'id" operator="null" />');if(!isFetchModified) isFetchModified=true;}});if(isFetchModified){outer.remove();targetFrame.$get("FetchXml",$get("resultRender")).value='<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true">'+xmlDoc.documentElement.innerHTML+'</fetch>';} targetFrame.changeArea(targetFrame.ResultsPage);targetFrame.$get('resultRender').submit();}else{alert('Cannot locate Advanced Find Frame');} void 0;
How to use this
The condition to indicate outer join is same as with the previous post i.e. you would specify the primary key of a link entity to be null, to indicate that you would like this link to be a outer join. In the screenshot below you are trying to find organisations without any contacts. When the script sees a link entity primary key, in this case contactid, set to null, it modifies this link as outer and places the appropriate filter criteria in the parent entity, in this case organisation. You basically have to build your conditions in the standard Advanced Find UI and execute the bookmarklet.
Image may be NSFW.
Clik here to view.
How it works
When you execute the Advanced Find, fetchxml and layoutxml is stored in the DOM. This script modifies this attribute and executes the Advanced Find again with the outer join bits added.
Open Issues
- Even though the underlying fetchxml has been manipulated, the condition builder UI is not updated to reflect this.
- Script error after the result page is rendered (Ignore this, as it doesn’t affect the results)
I have tested this only in CRMOnline with Firefox and Chrome.
Image may be NSFW.
Clik here to view.
Clik here to view.
