<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Comments on: 250,000 Tests for Uniqueness Per Second &#8212; Ain&#8217;t No Biggie</title>
	<atom:link href="http://oraclesponge.wordpress.com/2008/04/02/250000-tests-for-uniqueness-per-second-aint-no-biggie/feed/" rel="self" type="application/rss+xml" />
	<link>http://oraclesponge.wordpress.com/2008/04/02/250000-tests-for-uniqueness-per-second-aint-no-biggie/</link>
	<description>Oracle Data Warehouse Design and Architecture</description>
	<pubDate>Fri, 04 Jul 2008 18:51:32 +0000</pubDate>
	<generator>http://wordpress.org/?v=MU</generator>
		<item>
		<title>By: David Aldridge</title>
		<link>http://oraclesponge.wordpress.com/2008/04/02/250000-tests-for-uniqueness-per-second-aint-no-biggie/#comment-50928</link>
		<dc:creator>David Aldridge</dc:creator>
		<pubDate>Wed, 09 Apr 2008 20:25:53 +0000</pubDate>
		<guid isPermaLink="false">http://oraclesponge.wordpress.com/?p=363#comment-50928</guid>
		<description>I ran a quick test, Bob, but it wasn't encouraging I'm afraid. I didn't want to post anything on it till I was sure but it looked really really slow. I think it was something like 100 seconds versus 1 second ...</description>
		<content:encoded><![CDATA[<p>I ran a quick test, Bob, but it wasn&#8217;t encouraging I&#8217;m afraid. I didn&#8217;t want to post anything on it till I was sure but it looked really really slow. I think it was something like 100 seconds versus 1 second &#8230;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Bob B</title>
		<link>http://oraclesponge.wordpress.com/2008/04/02/250000-tests-for-uniqueness-per-second-aint-no-biggie/#comment-50922</link>
		<dc:creator>Bob B</dc:creator>
		<pubDate>Wed, 09 Apr 2008 15:38:09 +0000</pubDate>
		<guid isPermaLink="false">http://oraclesponge.wordpress.com/?p=363#comment-50922</guid>
		<description>I'm curious if you've had a chance to compare this to the procedural method?</description>
		<content:encoded><![CDATA[<p>I&#8217;m curious if you&#8217;ve had a chance to compare this to the procedural method?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Aldridge</title>
		<link>http://oraclesponge.wordpress.com/2008/04/02/250000-tests-for-uniqueness-per-second-aint-no-biggie/#comment-50909</link>
		<dc:creator>David Aldridge</dc:creator>
		<pubDate>Fri, 04 Apr 2008 17:03:52 +0000</pubDate>
		<guid isPermaLink="false">http://oraclesponge.wordpress.com/?p=363#comment-50909</guid>
		<description>Wow ... turns out that Fridays aren't reserved for bad news all the time afterall. I always thought I ought to learn more about the model clause, and now you give me the perfect opportunity. I'm one of those who can't learn something without a practical problem to solve. It's a debilitating handicap.

I'll look further into this and see how it scales against a real multimillion row data set.

Thanks very much indeed Bob. I'll post back with results.</description>
		<content:encoded><![CDATA[<p>Wow &#8230; turns out that Fridays aren&#8217;t reserved for bad news all the time afterall. I always thought I ought to learn more about the model clause, and now you give me the perfect opportunity. I&#8217;m one of those who can&#8217;t learn something without a practical problem to solve. It&#8217;s a debilitating handicap.</p>
<p>I&#8217;ll look further into this and see how it scales against a real multimillion row data set.</p>
<p>Thanks very much indeed Bob. I&#8217;ll post back with results.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Bob B</title>
		<link>http://oraclesponge.wordpress.com/2008/04/02/250000-tests-for-uniqueness-per-second-aint-no-biggie/#comment-50907</link>
		<dc:creator>Bob B</dc:creator>
		<pubDate>Fri, 04 Apr 2008 15:36:36 +0000</pubDate>
		<guid isPermaLink="false">http://oraclesponge.wordpress.com/?p=363#comment-50907</guid>
		<description>Huzzah, model clause to the rescue.

&lt;blockquote&gt;
SELECT SRC_ID, TGT_ID
FROM (
  SELECT SRC_ID, TGT_ID, MATCH
  FROM SS_SET
  MODEL
  DIMENSION BY (SRC_ID, TGT_ID)
  MEASURES (SRC_DATE, TGT_DATE, 0 MATCH)
  RULES (
    MATCH[ANY,ANY] ORDER BY SRC_DATE DESC, TGT_DATE ASC = CASE WHEN sum(MATCH)[ANY,CV()] = 0 AND sum(MATCH)[CV(),ANY] = 0 THEN 1 ELSE MATCH[CV(),CV()] END
  ) 
)
WHERE MATCH = 1
&lt;/blockquote&gt;

I'm not sure how fast this will work with the type and volume of your data set, but it was fun trying to figure out how to do it in SQL.</description>
		<content:encoded><![CDATA[<p>Huzzah, model clause to the rescue.</p>
<blockquote><p>
SELECT SRC_ID, TGT_ID<br />
FROM (<br />
  SELECT SRC_ID, TGT_ID, MATCH<br />
  FROM SS_SET<br />
  MODEL<br />
  DIMENSION BY (SRC_ID, TGT_ID)<br />
  MEASURES (SRC_DATE, TGT_DATE, 0 MATCH)<br />
  RULES (<br />
    MATCH[ANY,ANY] ORDER BY SRC_DATE DESC, TGT_DATE ASC = CASE WHEN sum(MATCH)[ANY,CV()] = 0 AND sum(MATCH)[CV(),ANY] = 0 THEN 1 ELSE MATCH[CV(),CV()] END<br />
  )<br />
)<br />
WHERE MATCH = 1
</p></blockquote>
<p>I&#8217;m not sure how fast this will work with the type and volume of your data set, but it was fun trying to figure out how to do it in SQL.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Gabe</title>
		<link>http://oraclesponge.wordpress.com/2008/04/02/250000-tests-for-uniqueness-per-second-aint-no-biggie/#comment-50899</link>
		<dc:creator>Gabe</dc:creator>
		<pubDate>Thu, 03 Apr 2008 20:12:12 +0000</pubDate>
		<guid isPermaLink="false">http://oraclesponge.wordpress.com/?p=363#comment-50899</guid>
		<description>Well, I only had &lt;i&gt;my&lt;/i&gt; interpretation of what the &lt;i&gt;real&lt;/i&gt; rules were.

You were talking about two (hence independent) data sets with, seemingly, a many-to-many relationship which needed resolving. It wasn’t obvious there was also a pool of &lt;i&gt;candidate&lt;/i&gt; connections ... your sample data set seemed to be just that, sample data ... and not sample data with a rule built into it.

Also, with the old data set you were ordering and pushing into the memory stack the same pair of attributes. Now you’re ordering by a pair of attributes but push into the memory stack a different pair of attributes. Not exactly the same thing.

Even with your new test case there seem to be built-in assumptions which may or may not be relevant. For example, update src_date and tgt_date, for all rows, to the same date. With that, the result of your query (and algorithm for that matter) becomes non-deterministic ... but why that would not constitute a &lt;i&gt;real&lt;/i&gt; data set, I don’t know.

Having said that, I think your approach is quite valid and elegant. The query that I did was not substantially faster than your approach and, if anything, would get - given the extra rules required - only more complicated and slower.

I cannot think of a linear sql solution ... a solution here appears to require a recursive approach. To do that without pl/sql would need some sort of hierarchical query (that a &lt;i&gt;connect by&lt;/i&gt; query is &lt;i&gt;straight&lt;/i&gt; sql is questionable anyway). Given your volume, the hierarchical query would be slooooowww! Hence I would not even attempt that.

Which brings me back to ... someone may come up with a liner sql solution and I would be curious to see it; but I know it won’t be faster than what you have. As long as you don’t blow/page the user memory with those pl/sql arrays I think you’re good. Hopefully this matching is a one-time affair since any insert/update/delete has the potential to destabilize the whole thing (change the result and/or make it non-deterministic).

The only thing I would do differently is to pipe the results and do away with the need to reset those global arrays, etc. It was also faster in my tests for 1 million rows though it may be different for your real data:

&lt;code&gt;
create or replace type typ as object ( s number, t number );
/
show errors

create or replace type arr as table of typ;
/
show errors

create or replace function f return arr
pipelined
as
  type numArr is table of number index by binary_integer;
  s  numArr;
  t  numArr;
begin
  for crs in ( select src_id, tgt_id from ss_set order by src_date desc, tgt_date asc)
  loop
    if s.exists(crs.src_id) or t.exists(crs.tgt_id) then
      null;
    else
       s(crs.src_id) := 1; t(crs.tgt_id) := 1;
       pipe row ( typ(crs.src_id, crs.tgt_id) ); 
    end if;
  end loop;
  return;
end;
/
show errors


a@B&#62; select * from table(f);

         S          T
---------- ----------
         5          1
         1          3
         4          4
         2          2
&lt;/code&gt;</description>
		<content:encoded><![CDATA[<p>Well, I only had <i>my</i> interpretation of what the <i>real</i> rules were.</p>
<p>You were talking about two (hence independent) data sets with, seemingly, a many-to-many relationship which needed resolving. It wasn’t obvious there was also a pool of <i>candidate</i> connections &#8230; your sample data set seemed to be just that, sample data &#8230; and not sample data with a rule built into it.</p>
<p>Also, with the old data set you were ordering and pushing into the memory stack the same pair of attributes. Now you’re ordering by a pair of attributes but push into the memory stack a different pair of attributes. Not exactly the same thing.</p>
<p>Even with your new test case there seem to be built-in assumptions which may or may not be relevant. For example, update src_date and tgt_date, for all rows, to the same date. With that, the result of your query (and algorithm for that matter) becomes non-deterministic &#8230; but why that would not constitute a <i>real</i> data set, I don’t know.</p>
<p>Having said that, I think your approach is quite valid and elegant. The query that I did was not substantially faster than your approach and, if anything, would get - given the extra rules required - only more complicated and slower.</p>
<p>I cannot think of a linear sql solution &#8230; a solution here appears to require a recursive approach. To do that without pl/sql would need some sort of hierarchical query (that a <i>connect by</i> query is <i>straight</i> sql is questionable anyway). Given your volume, the hierarchical query would be slooooowww! Hence I would not even attempt that.</p>
<p>Which brings me back to &#8230; someone may come up with a liner sql solution and I would be curious to see it; but I know it won’t be faster than what you have. As long as you don’t blow/page the user memory with those pl/sql arrays I think you’re good. Hopefully this matching is a one-time affair since any insert/update/delete has the potential to destabilize the whole thing (change the result and/or make it non-deterministic).</p>
<p>The only thing I would do differently is to pipe the results and do away with the need to reset those global arrays, etc. It was also faster in my tests for 1 million rows though it may be different for your real data:</p>
<p><code><br />
create or replace type typ as object ( s number, t number );<br />
/<br />
show errors</p>
<p>create or replace type arr as table of typ;<br />
/<br />
show errors</p>
<p>create or replace function f return arr<br />
pipelined<br />
as<br />
  type numArr is table of number index by binary_integer;<br />
  s  numArr;<br />
  t  numArr;<br />
begin<br />
  for crs in ( select src_id, tgt_id from ss_set order by src_date desc, tgt_date asc)<br />
  loop<br />
    if s.exists(crs.src_id) or t.exists(crs.tgt_id) then<br />
      null;<br />
    else<br />
       s(crs.src_id) := 1; t(crs.tgt_id) := 1;<br />
       pipe row ( typ(crs.src_id, crs.tgt_id) );<br />
    end if;<br />
  end loop;<br />
  return;<br />
end;<br />
/<br />
show errors</p>
<p>a@B&gt; select * from table(f);</p>
<p>         S          T<br />
---------- ----------<br />
         5          1<br />
         1          3<br />
         4          4<br />
         2          2<br />
</code></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Aldridge</title>
		<link>http://oraclesponge.wordpress.com/2008/04/02/250000-tests-for-uniqueness-per-second-aint-no-biggie/#comment-50898</link>
		<dc:creator>David Aldridge</dc:creator>
		<pubDate>Thu, 03 Apr 2008 16:41:37 +0000</pubDate>
		<guid isPermaLink="false">http://oraclesponge.wordpress.com/?p=363#comment-50898</guid>
		<description>Gabe, I think that works for my silly simple data set, but it's not actually implementing the real rules is it?</description>
		<content:encoded><![CDATA[<p>Gabe, I think that works for my silly simple data set, but it&#8217;s not actually implementing the real rules is it?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Aldridge</title>
		<link>http://oraclesponge.wordpress.com/2008/04/02/250000-tests-for-uniqueness-per-second-aint-no-biggie/#comment-50897</link>
		<dc:creator>David Aldridge</dc:creator>
		<pubDate>Thu, 03 Apr 2008 16:34:24 +0000</pubDate>
		<guid isPermaLink="false">http://oraclesponge.wordpress.com/?p=363#comment-50897</guid>
		<description>Yes, not all combinations are valid. So we have say 7 million sources and 8 million targets, and some subset of them join together through rather complex multivalue logic that is not relevant to this issue. We might average something like 3 &lt;i&gt;potential targets&lt;/i&gt; for each source, so something like 21 million joins out of which we have to find the real connections -- there might only be 2 million connections to be made because by the time you check the last of the sources all of their potential targets have already been connected-to by other sources.

Here's a crack at a better data set:

drop table ss_set;

create table ss_set (src_id number, src_date date, tgt_id number, tgt_date date);

insert into ss_set values (1,date '2007-06-01',1,date '2007-06-01');
insert into ss_set values (1,date '2007-06-01',2,date '2007-06-10');
insert into ss_set values (1,date '2007-06-01',3,date '2007-06-03');
insert into ss_set values (2,date '2007-05-01',1,date '2007-06-01');
insert into ss_set values (2,date '2007-05-01',2,date '2007-06-10');
insert into ss_set values (2,date '2007-05-01',4,date '2007-05-03');
insert into ss_set values (3,date '2007-07-01',1,date '2007-06-01');
insert into ss_set values (4,date '2007-05-20',2,date '2007-06-10');
insert into ss_set values (4,date '2007-05-20',4,date '2007-05-03');
insert into ss_set values (5,date '2007-08-01',1,date '2007-06-01');
commit;

So the ordered data set looks like this:

select src_id,tgt_id
 from   ss_set
 where  rownum &#62; 0
order by src_date desc, tgt_date asc
/

SRC_ID                 TGT_ID                 
---------------------- ---------------------- 
5                      1                      
3                      1                      
1                      1                      
1                      3                      
1                      2                      
4                      4                      
4                      2                      
2                      4                      
2                      1                      
2                      2  

And the final result should look like this:


exec ss.reset;
       
select * from       
(select src_id,tgt_id
 from   ss_set
 where  rownum &#62; 0
order by src_date desc, tgt_date asc)
where ss.is_new(src_id,tgt_id) = 1
/

SRC_ID                 TGT_ID                 
---------------------- ---------------------- 
5                      1                      
1                      3                      
4                      4                      
2                      2                      


Note that source 3 has no valid connection because its only candidate connecton was to target 1, and source 5 already connected to that because it has a later source date.

Hopefully this isn't too simple a data set ...</description>
		<content:encoded><![CDATA[<p>Yes, not all combinations are valid. So we have say 7 million sources and 8 million targets, and some subset of them join together through rather complex multivalue logic that is not relevant to this issue. We might average something like 3 <i>potential targets</i> for each source, so something like 21 million joins out of which we have to find the real connections &#8212; there might only be 2 million connections to be made because by the time you check the last of the sources all of their potential targets have already been connected-to by other sources.</p>
<p>Here&#8217;s a crack at a better data set:</p>
<p>drop table ss_set;</p>
<p>create table ss_set (src_id number, src_date date, tgt_id number, tgt_date date);</p>
<p>insert into ss_set values (1,date &#8216;2007-06-01&#8242;,1,date &#8216;2007-06-01&#8242;);<br />
insert into ss_set values (1,date &#8216;2007-06-01&#8242;,2,date &#8216;2007-06-10&#8242;);<br />
insert into ss_set values (1,date &#8216;2007-06-01&#8242;,3,date &#8216;2007-06-03&#8242;);<br />
insert into ss_set values (2,date &#8216;2007-05-01&#8242;,1,date &#8216;2007-06-01&#8242;);<br />
insert into ss_set values (2,date &#8216;2007-05-01&#8242;,2,date &#8216;2007-06-10&#8242;);<br />
insert into ss_set values (2,date &#8216;2007-05-01&#8242;,4,date &#8216;2007-05-03&#8242;);<br />
insert into ss_set values (3,date &#8216;2007-07-01&#8242;,1,date &#8216;2007-06-01&#8242;);<br />
insert into ss_set values (4,date &#8216;2007-05-20&#8242;,2,date &#8216;2007-06-10&#8242;);<br />
insert into ss_set values (4,date &#8216;2007-05-20&#8242;,4,date &#8216;2007-05-03&#8242;);<br />
insert into ss_set values (5,date &#8216;2007-08-01&#8242;,1,date &#8216;2007-06-01&#8242;);<br />
commit;</p>
<p>So the ordered data set looks like this:</p>
<p>select src_id,tgt_id<br />
 from   ss_set<br />
 where  rownum &gt; 0<br />
order by src_date desc, tgt_date asc<br />
/</p>
<p>SRC_ID                 TGT_ID<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
5                      1<br />
3                      1<br />
1                      1<br />
1                      3<br />
1                      2<br />
4                      4<br />
4                      2<br />
2                      4<br />
2                      1<br />
2                      2  </p>
<p>And the final result should look like this:</p>
<p>exec ss.reset;</p>
<p>select * from<br />
(select src_id,tgt_id<br />
 from   ss_set<br />
 where  rownum &gt; 0<br />
order by src_date desc, tgt_date asc)<br />
where ss.is_new(src_id,tgt_id) = 1<br />
/</p>
<p>SRC_ID                 TGT_ID<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
5                      1<br />
1                      3<br />
4                      4<br />
2                      2                      </p>
<p>Note that source 3 has no valid connection because its only candidate connecton was to target 1, and source 5 already connected to that because it has a later source date.</p>
<p>Hopefully this isn&#8217;t too simple a data set &#8230;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Gabe</title>
		<link>http://oraclesponge.wordpress.com/2008/04/02/250000-tests-for-uniqueness-per-second-aint-no-biggie/#comment-50896</link>
		<dc:creator>Gabe</dc:creator>
		<pubDate>Thu, 03 Apr 2008 16:27:30 +0000</pubDate>
		<guid isPermaLink="false">http://oraclesponge.wordpress.com/?p=363#comment-50896</guid>
		<description>&lt;code&gt;
a@B&#62; exec ss.reset;

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.00
a@B &#62;
a@B &#62; select * from
  2  (select s.num s_num,t.num t_num
  3  from   (select rownum num from dual connect by level &#60;= 10) s,
  4         (select rownum num from dual connect by level  0
  6  order by 1 desc, 2 asc)
  7  where ss.is_new(s_num,t_num) = 1
  8  /

     S_NUM      T_NUM
---------- ----------
        10          1
         9          2
         8          3
         7          4
         6          5

Elapsed: 00:00:00.01
a@B &#62;
a@B &#62; with t as
  2       ( select s.num s_num,t.num t_num
  3         from   (select rownum num from dual connect by level &#60;= 10) s,
  4                (select rownum num from dual connect by level &#60;= 5)  t
  5       )
  6      ,j as
  7       (
  8  select s_num, dense_rank() over (order by s_num desc) rs
  9        ,t_num, dense_rank() over (order by t_num asc)  rt
 10  from   t
 11  --order by s_num desc, t_num asc
 12       )
 13  select s_num, t_num
 14  from   j
 15  where  rs = rt
 16  ;

     S_NUM      T_NUM
---------- ----------
        10          1
         9          2
         8          3
         7          4
         6          5

Elapsed: 00:00:00.01 
&lt;/code&gt;</description>
		<content:encoded><![CDATA[<p><code><br />
a@B&gt; exec ss.reset;</p>
<p>PL/SQL procedure successfully completed.</p>
<p>Elapsed: 00:00:00.00<br />
a@B &gt;<br />
a@B &gt; select * from<br />
  2  (select s.num s_num,t.num t_num<br />
  3  from   (select rownum num from dual connect by level &lt;= 10) s,<br />
  4         (select rownum num from dual connect by level  0<br />
  6  order by 1 desc, 2 asc)<br />
  7  where ss.is_new(s_num,t_num) = 1<br />
  8  /</p>
<p>     S_NUM      T_NUM<br />
---------- ----------<br />
        10          1<br />
         9          2<br />
         8          3<br />
         7          4<br />
         6          5</p>
<p>Elapsed: 00:00:00.01<br />
a@B &gt;<br />
a@B &gt; with t as<br />
  2       ( select s.num s_num,t.num t_num<br />
  3         from   (select rownum num from dual connect by level &lt;= 10) s,<br />
  4                (select rownum num from dual connect by level &lt;= 5)  t<br />
  5       )<br />
  6      ,j as<br />
  7       (<br />
  8  select s_num, dense_rank() over (order by s_num desc) rs<br />
  9        ,t_num, dense_rank() over (order by t_num asc)  rt<br />
 10  from   t<br />
 11  --order by s_num desc, t_num asc<br />
 12       )<br />
 13  select s_num, t_num<br />
 14  from   j<br />
 15  where  rs = rt<br />
 16  ;</p>
<p>     S_NUM      T_NUM<br />
---------- ----------<br />
        10          1<br />
         9          2<br />
         8          3<br />
         7          4<br />
         6          5</p>
<p>Elapsed: 00:00:00.01<br />
</code></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Bob B</title>
		<link>http://oraclesponge.wordpress.com/2008/04/02/250000-tests-for-uniqueness-per-second-aint-no-biggie/#comment-50894</link>
		<dc:creator>Bob B</dc:creator>
		<pubDate>Thu, 03 Apr 2008 15:56:52 +0000</pubDate>
		<guid isPermaLink="false">http://oraclesponge.wordpress.com/?p=363#comment-50894</guid>
		<description>Could you give a more concrete example.  I'm assuming that there is a defined relationship between source and target such that there are some source/target combinations that are not valid.  Otherwise you could use analytics to enumerate the source in descending order and the target in ascending order and select out the rows where the source and target have the same number.

WITH src_data AS (
  SELECT ROWNUM val
  FROM DUAL
  CONNECT BY LEVEL &#60;= 1000
), tgt_data AS (
  SELECT ROWNUM + 77 val
  FROM DUAL
  CONNECT BY LEVEL &#60;= 1000
)
SELECT *
FROM (
  SELECT 
    sd.VAL src_val,
    td.VAL tgt_val,
    ROW_NUMBER() OVER ( ORDER BY sd.VAL DESC ) src_num,
    ROW_NUMBER() OVER ( ORDER BY td.VAL ) tgt_num
  FROM SRC_DATA sd, TGT_DATA td
) L1
WHERE L1.src_num = L1.tgt_num</description>
		<content:encoded><![CDATA[<p>Could you give a more concrete example.  I&#8217;m assuming that there is a defined relationship between source and target such that there are some source/target combinations that are not valid.  Otherwise you could use analytics to enumerate the source in descending order and the target in ascending order and select out the rows where the source and target have the same number.</p>
<p>WITH src_data AS (<br />
  SELECT ROWNUM val<br />
  FROM DUAL<br />
  CONNECT BY LEVEL &lt;= 1000<br />
), tgt_data AS (<br />
  SELECT ROWNUM + 77 val<br />
  FROM DUAL<br />
  CONNECT BY LEVEL &lt;= 1000<br />
)<br />
SELECT *<br />
FROM (<br />
  SELECT<br />
    sd.VAL src_val,<br />
    td.VAL tgt_val,<br />
    ROW_NUMBER() OVER ( ORDER BY sd.VAL DESC ) src_num,<br />
    ROW_NUMBER() OVER ( ORDER BY td.VAL ) tgt_num<br />
  FROM SRC_DATA sd, TGT_DATA td<br />
) L1<br />
WHERE L1.src_num = L1.tgt_num</p>
]]></content:encoded>
	</item>
</channel>
</rss>
