<?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"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
		>
<channel>
	<title>Comments on: Row Values to Comma Separated Lists, an Overly Complicated Use Case Example</title>
	<atom:link href="http://hoopercharles.wordpress.com/2011/05/26/row-values-to-comma-separated-lists-an-overly-complicated-use-case-example/feed/" rel="self" type="application/rss+xml" />
	<link>http://hoopercharles.wordpress.com/2011/05/26/row-values-to-comma-separated-lists-an-overly-complicated-use-case-example/</link>
	<description>Miscellaneous Random Oracle Topics: Stop, Think, ... Understand</description>
	<lastBuildDate>Mon, 13 May 2013 14:10:06 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
	<item>
		<title>By: Charles Hooper</title>
		<link>http://hoopercharles.wordpress.com/2011/05/26/row-values-to-comma-separated-lists-an-overly-complicated-use-case-example/#comment-3245</link>
		<dc:creator><![CDATA[Charles Hooper]]></dc:creator>
		<pubDate>Fri, 27 May 2011 18:37:54 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=4873#comment-3245</guid>
		<description><![CDATA[Narendra,

Interesting points.  Let&#039;s double-check the accurary of the statements:

http://jonathanlewis.wordpress.com/2008/02/17/pushing-predicates-2/
http://www.jlcomp.demon.co.uk/push_pred.html
From the above links, PUSH_PRED and NO_PUSH_PRED hints are associated with the &quot;join predicate pushdown (JPPD)&quot; section of a 10053 trace file. The predicates that I was expecting to see generated are actually generated in the filter &quot;push-down (FPD)&quot; section (see the test case 10053 output below).

---

http://download.oracle.com/docs/cd/E14072_01/server.112/e10592/queries003.htm
&lt;blockquote&gt;
Oracle processes hierarchical queries as follows:
•A join, if present, is evaluated first, whether the join is specified in the FROM clause or with WHERE clause predicates.
•The CONNECT BY condition is evaluated.
•Any remaining WHERE clause predicates are evaluated.

Oracle then uses the information from these evaluations to form the hierarchy using the following steps:
1.Oracle selects the root row(s) of the hierarchy—those rows that satisfy the START WITH condition.
2.Oracle selects the child rows of each root row. Each child row must satisfy the condition of the CONNECT BY condition with respect to one of the root rows.
3.Oracle selects successive generations of child rows. Oracle first selects the children of the rows returned in step 2, and then the children of those children, and so on. Oracle always selects children by evaluating the CONNECT BY condition with respect to a current parent row.
4.If the query contains a WHERE clause without a join, then Oracle eliminates all rows from the hierarchy that do not satisfy the condition of the WHERE clause. Oracle evaluates this condition for each row individually, rather than removing all the children of a row that does not satisfy the condition.
5.Oracle returns the rows in the order shown in Figure 9-1. In the diagram, children appear below their parents. For an explanation of hierarchical trees, see Figure 2-1, &quot;Hierarchical Tree&quot;.
&lt;/blockquote&gt;

It appears that your two points are valid.  Thank you for the correction.

Test case script:
&lt;pre&gt;
CREATE TABLE T1 AS
SELECT
  ROWNUM C1,
  DBMS_RANDOM.STRING(&#039;A&#039;,20) C2,
  SYSDATE+ROWNUM/100 C3
FROM
  DUAL
CONNECT BY
  LEVEL&lt;=100000;

CREATE TABLE T2 AS
SELECT
  ROWNUM*2 C1,
  DBMS_RANDOM.STRING(&#039;A&#039;,20) C2,
  SYSDATE+ROWNUM/100 C3
FROM
  DUAL
CONNECT BY
  LEVEL&lt;=50000;
&lt;/pre&gt;

&lt;pre&gt;
ALTER SESSION SET TRACEFILE_IDENTIFIER=&#039;WATCH_TRANSFORM&#039;; 
ALTER SESSION SET EVENTS &#039;10053 TRACE NAME CONTEXT FOREVER, LEVEL 1&#039;;

SELECT /*+ NO_MERGE(V) PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V
WHERE
  V.C1 BETWEEN 1 AND 10;

SELECT /*+ NO_MERGE(V) NO_PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V
WHERE
  V.C1 BETWEEN 1 AND 10;

SELECT /*+ NO_MERGE(V) PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V,
  T2
WHERE
  T2.C1 BETWEEN 1 AND 20
  AND T2.C1=V.C1;

SELECT /*+ NO_MERGE(V) NO_PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V,
  T2
WHERE
  T2.C1 BETWEEN 1 AND 20
  AND T2.C1=V.C1;

ALTER SESSION SET EVENTS &#039;10053 TRACE NAME CONTEXT OFF&#039;;
&lt;/pre&gt;

Sections of the generated 10053 trace file:
&lt;pre&gt;
----- Current SQL Statement for this session (sql_id=fxa990xn82j8u) -----
SELECT /*+ NO_MERGE(V) PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V
WHERE
  V.C1 BETWEEN 1 AND 10

JPPD:     JPPD bypassed: View has unsupported constructs.

**************************
Predicate Move-Around (PM)
**************************
PM:   Passed validity checks.
PM:   Pushed down predicate &quot;T1&quot;.&quot;C1&quot;&gt;=1
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:   Pushed down predicate &quot;T1&quot;.&quot;C1&quot;&lt;=10
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:     PM bypassed: checking.
query block SEL$1 (#0) unchanged
FPD: Considering simple filter push in query block SEL$1 (#0)
 ?? 
FPD: Considering simple filter push in query block SEL$2 (#0)
&quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=10
try to generate transitive predicate from check constraints for query block SEL$2 (#0)
finally: &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=10 AND 1&lt;=10
FPD:   transitive predicates are generated in query block SEL$2 (#0)
&quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=10 AND 1&lt;=10
apadrv-start sqlid=17197321763885761818

Final query after transformations:******* UNPARSED QUERY IS *******
SELECT /*+ PUSH_PRED (&quot;V&quot;) NO_MERGE (&quot;V&quot;) */ &quot;V&quot;.&quot;C1&quot; &quot;C1&quot;,&quot;V&quot;.&quot;C2&quot; &quot;C2&quot; FROM  
(SELECT &quot;T1&quot;.&quot;C1&quot; &quot;C1&quot;,&quot;T1&quot;.&quot;C2&quot; &quot;C2&quot; FROM &quot;TESTUSER&quot;.&quot;T1&quot; &quot;T1&quot; WHERE &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=10 AND 1&lt;=10) &quot;V&quot;

============
Plan Table
============
--------------------------------------+-----------------------------------+
&#124; Id  &#124; Operation           &#124; Name    &#124; Rows  &#124; Bytes &#124; Cost  &#124; Time      &#124;
--------------------------------------+-----------------------------------+
&#124; 0   &#124; SELECT STATEMENT    &#124;         &#124;       &#124;       &#124;    60 &#124;           &#124;
&#124; 1   &#124;  VIEW               &#124;         &#124;     6 &#124;   12K &#124;    60 &#124;  00:00:01 &#124;
&#124; 2   &#124;   TABLE ACCESS FULL &#124; T1      &#124;     6 &#124;   12K &#124;    60 &#124;  00:00:01 &#124;
--------------------------------------+-----------------------------------+
Predicate Information:
----------------------
2 - filter((&quot;C1&quot;&gt;=1 AND &quot;C1&quot;&lt;=10))

Dumping Hints
=============
  atom_hint=(@=00000000161B15E0 err=0 resol=1 used=1 token=895 org=1 lvl=3 txt=PUSH_PRED (&quot;V&quot;) )
  atom_hint=(@=00000000161B1858 err=0 resol=1 used=1 token=876 org=1 lvl=3 txt=NO_MERGE (&quot;V&quot;) )
&lt;/pre&gt;
The above seems to indicate that the PUSH_PRED and NO_MERGE hints were both used, and we can see by the modified WHERE clause that the predicates present outside the inline view were 

transferred inside the inline view (caused by &quot;simple filter push&quot;).
 
&lt;pre&gt;
SELECT /*+ NO_MERGE(V) NO_PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V
WHERE
  V.C1 BETWEEN 1 AND 10

JPPD:     JPPD bypassed: View has unsupported constructs.

**************************
Predicate Move-Around (PM)
**************************
PM:   Passed validity checks.
PM:   Pushed down predicate &quot;T1&quot;.&quot;C1&quot;&gt;=1
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:   Pushed down predicate &quot;T1&quot;.&quot;C1&quot;&lt;=10
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:     PM bypassed: checking.
query block SEL$1 (#0) unchanged
FPD: Considering simple filter push in query block SEL$1 (#0)
 ?? 
FPD: Considering simple filter push in query block SEL$2 (#0)
&quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=10
try to generate transitive predicate from check constraints for query block SEL$2 (#0)
finally: &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=10 AND 1&lt;=10
FPD:   transitive predicates are generated in query block SEL$2 (#0)
&quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=10 AND 1&lt;=10
apadrv-start sqlid=3636309318118712829
 
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT /*+ NO_PUSH_PRED (&quot;V&quot;) NO_MERGE (&quot;V&quot;) */ &quot;V&quot;.&quot;C1&quot; &quot;C1&quot;,&quot;V&quot;.&quot;C2&quot; &quot;C2&quot; FROM  
(SELECT &quot;T1&quot;.&quot;C1&quot; &quot;C1&quot;,&quot;T1&quot;.&quot;C2&quot; &quot;C2&quot; FROM &quot;TESTUSER&quot;.&quot;T1&quot; &quot;T1&quot; WHERE &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=10 AND 1&lt;=10) &quot;V&quot;

============
Plan Table
============
--------------------------------------+-----------------------------------+
&#124; Id  &#124; Operation           &#124; Name    &#124; Rows  &#124; Bytes &#124; Cost  &#124; Time      &#124;
--------------------------------------+-----------------------------------+
&#124; 0   &#124; SELECT STATEMENT    &#124;         &#124;       &#124;       &#124;    60 &#124;           &#124;
&#124; 1   &#124;  VIEW               &#124;         &#124;     6 &#124;   12K &#124;    60 &#124;  00:00:01 &#124;
&#124; 2   &#124;   TABLE ACCESS FULL &#124; T1      &#124;     6 &#124;   12K &#124;    60 &#124;  00:00:01 &#124;
--------------------------------------+-----------------------------------+
Predicate Information:
----------------------
2 - filter((&quot;C1&quot;&gt;=1 AND &quot;C1&quot;&lt;=10))
 
Dumping Hints
=============
  atom_hint=(@=00000000161B15D8 err=0 resol=1 used=0 token=880 org=1 lvl=3 txt=NO_PUSH_PRED (&quot;V&quot;) )
  atom_hint=(@=00000000161B1850 err=0 resol=1 used=1 token=876 org=1 lvl=3 txt=NO_MERGE (&quot;V&quot;) )
&lt;/pre&gt;
The above seems to indicate that the NO_PUSH_PRED hint was NOT used and NO_MERGE hints was used, and we can see by the modified WHERE clause that the predicates present outside the inline 

view were transferred inside the inline view.

&lt;pre&gt;
SELECT /*+ NO_MERGE(V) PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V,
  T2
WHERE
  T2.C1 BETWEEN 1 AND 20
  AND T2.C1=V.C1

JPPD:     JPPD bypassed: View has unsupported constructs.

**************************
Predicate Move-Around (PM)
**************************
PM:   Passed validity checks.
PM: Added transitive pred &quot;V&quot;.&quot;C1&quot;&gt;=1
 in query block SEL$1 (#0)
PM: Added transitive pred &quot;V&quot;.&quot;C1&quot;&lt;=20
 in query block SEL$1 (#0)
PM:   Pushed down predicate &quot;T1&quot;.&quot;C1&quot;&gt;=1
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:   Pushed down predicate &quot;T1&quot;.&quot;C1&quot;&lt;=20
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:     PM bypassed: checking.
query block SEL$1 (#0) unchanged
FPD: Considering simple filter push in query block SEL$1 (#0)
&quot;T2&quot;.&quot;C1&quot;&gt;=1 AND &quot;T2&quot;.&quot;C1&quot;&lt;=20 AND &quot;T2&quot;.&quot;C1&quot;=&quot;V&quot;.&quot;C1&quot;
try to generate transitive predicate from check constraints for query block SEL$1 (#0)
finally: &quot;T2&quot;.&quot;C1&quot;&gt;=1 AND &quot;T2&quot;.&quot;C1&quot;&lt;=20 AND &quot;T2&quot;.&quot;C1&quot;=&quot;V&quot;.&quot;C1&quot; AND 1&lt;=20 AND &quot;V&quot;.&quot;C1&quot;&gt;=1 AND &quot;V&quot;.&quot;C1&quot;&lt;=20

FPD:   transitive predicates are generated in query block SEL$1 (#0)
&quot;T2&quot;.&quot;C1&quot;&gt;=1 AND &quot;T2&quot;.&quot;C1&quot;&lt;=20 AND &quot;T2&quot;.&quot;C1&quot;=&quot;V&quot;.&quot;C1&quot; AND 1&lt;=20 AND &quot;V&quot;.&quot;C1&quot;&gt;=1 AND &quot;V&quot;.&quot;C1&quot;&lt;=20
JPPD:     JPPD bypassed: View not on right-side of outer-join.         &lt;======================
FPD:   Following are pushed to where clause of query block SEL$2 (#0)
1&lt;=20 AND &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=20
FPD: Considering simple filter push in query block SEL$2 (#0)
&quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=20 AND 1&lt;=20 AND &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=20
try to generate transitive predicate from check constraints for query block SEL$2 (#0)
finally: &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=20 AND 1&lt;=20 AND &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=20
 
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT /*+ PUSH_PRED (&quot;V&quot;) NO_MERGE (&quot;V&quot;) */ &quot;V&quot;.&quot;C1&quot; &quot;C1&quot;,&quot;V&quot;.&quot;C2&quot; &quot;C2&quot; FROM  
(SELECT &quot;T1&quot;.&quot;C1&quot; &quot;C1&quot;,&quot;T1&quot;.&quot;C2&quot; &quot;C2&quot; FROM &quot;TESTUSER&quot;.&quot;T1&quot; &quot;T1&quot; WHERE &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=20 AND 1&lt;=20 AND &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=20) &quot;V&quot;,
&quot;TESTUSER&quot;.&quot;T2&quot; &quot;T2&quot; WHERE &quot;T2&quot;.&quot;C1&quot;&gt;=1 AND &quot;T2&quot;.&quot;C1&quot;&lt;=20 AND &quot;T2&quot;.&quot;C1&quot;=&quot;V&quot;.&quot;C1&quot;

============
Plan Table
============
---------------------------------------+-----------------------------------+
&#124; Id  &#124; Operation            &#124; Name    &#124; Rows  &#124; Bytes &#124; Cost  &#124; Time      &#124;
---------------------------------------+-----------------------------------+
&#124; 0   &#124; SELECT STATEMENT     &#124;         &#124;       &#124;       &#124;    93 &#124;           &#124;
&#124; 1   &#124;  HASH JOIN           &#124;         &#124;     3 &#124;  6084 &#124;    93 &#124;  00:00:01 &#124;
&#124; 2   &#124;   TABLE ACCESS FULL  &#124; T2      &#124;     3 &#124;    39 &#124;    32 &#124;  00:00:01 &#124;
&#124; 3   &#124;   VIEW               &#124;         &#124;     6 &#124;   12K &#124;    60 &#124;  00:00:01 &#124;
&#124; 4   &#124;    TABLE ACCESS FULL &#124; T1      &#124;     6 &#124;   12K &#124;    60 &#124;  00:00:01 &#124;
---------------------------------------+-----------------------------------+
Predicate Information:
----------------------
1 - access(&quot;T2&quot;.&quot;C1&quot;=&quot;V&quot;.&quot;C1&quot;)
2 - filter((&quot;T2&quot;.&quot;C1&quot;&gt;=1 AND &quot;T2&quot;.&quot;C1&quot;&lt;=20))
4 - filter((&quot;C1&quot;&gt;=1 AND &quot;C1&quot;&lt;=20))
 
Dumping Hints
=============
  atom_hint=(@=00000000161B15C8 err=0 resol=1 used=1 token=895 org=1 lvl=3 txt=PUSH_PRED (&quot;V&quot;) )
  atom_hint=(@=00000000161B1840 err=0 resol=1 used=1 token=876 org=1 lvl=3 txt=NO_MERGE (&quot;V&quot;) )
&lt;/pre&gt;
The above seems to indicate that the PUSH_PRED and NO_MERGE hints were both used, and we can see by the modified WHERE clause that the predicates present outside the inline view were 

transferred inside the inline view (twice!).

&lt;pre&gt;
SELECT /*+ NO_MERGE(V) NO_PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V,
  T2
WHERE
  T2.C1 BETWEEN 1 AND 20
  AND T2.C1=V.C1

JPPD:     JPPD bypassed: View has unsupported constructs.

**************************
Predicate Move-Around (PM)
**************************
PM:   Passed validity checks.
PM: Added transitive pred &quot;V&quot;.&quot;C1&quot;&gt;=1
 in query block SEL$1 (#0)
PM: Added transitive pred &quot;V&quot;.&quot;C1&quot;&lt;=20
 in query block SEL$1 (#0)
PM:   Pushed down predicate &quot;T1&quot;.&quot;C1&quot;&gt;=1
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:   Pushed down predicate &quot;T1&quot;.&quot;C1&quot;&lt;=20
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:     PM bypassed: checking.
query block SEL$1 (#0) unchanged
FPD: Considering simple filter push in query block SEL$1 (#0)
&quot;T2&quot;.&quot;C1&quot;&gt;=1 AND &quot;T2&quot;.&quot;C1&quot;&lt;=20 AND &quot;T2&quot;.&quot;C1&quot;=&quot;V&quot;.&quot;C1&quot;
try to generate transitive predicate from check constraints for query block SEL$1 (#0)
finally: &quot;T2&quot;.&quot;C1&quot;&gt;=1 AND &quot;T2&quot;.&quot;C1&quot;&lt;=20 AND &quot;T2&quot;.&quot;C1&quot;=&quot;V&quot;.&quot;C1&quot; AND 1&lt;=20 AND &quot;V&quot;.&quot;C1&quot;&gt;=1 AND &quot;V&quot;.&quot;C1&quot;&lt;=20

FPD:   transitive predicates are generated in query block SEL$1 (#0)
&quot;T2&quot;.&quot;C1&quot;&gt;=1 AND &quot;T2&quot;.&quot;C1&quot;&lt;=20 AND &quot;T2&quot;.&quot;C1&quot;=&quot;V&quot;.&quot;C1&quot; AND 1&lt;=20 AND &quot;V&quot;.&quot;C1&quot;&gt;=1 AND &quot;V&quot;.&quot;C1&quot;&lt;=20
JPPD:     JPPD bypassed: View not on right-side of outer-join.
FPD:   Following are pushed to where clause of query block SEL$2 (#0)
1&lt;=20 AND &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=20
FPD: Considering simple filter push in query block SEL$2 (#0)
&quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=20 AND 1&lt;=20 AND &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=20
try to generate transitive predicate from check constraints for query block SEL$2 (#0)
finally: &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=20 AND 1&lt;=20 AND &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=20

Final query after transformations:******* UNPARSED QUERY IS *******
SELECT /*+ NO_PUSH_PRED (&quot;V&quot;) NO_MERGE (&quot;V&quot;) */ &quot;V&quot;.&quot;C1&quot; &quot;C1&quot;,&quot;V&quot;.&quot;C2&quot; &quot;C2&quot; FROM  
(SELECT &quot;T1&quot;.&quot;C1&quot; &quot;C1&quot;,&quot;T1&quot;.&quot;C2&quot; &quot;C2&quot; FROM &quot;TESTUSER&quot;.&quot;T1&quot; &quot;T1&quot; WHERE &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=20 AND 1&lt;=20 AND &quot;T1&quot;.&quot;C1&quot;&gt;=1 AND &quot;T1&quot;.&quot;C1&quot;&lt;=20) &quot;V&quot;,
&quot;TESTUSER&quot;.&quot;T2&quot; &quot;T2&quot; WHERE &quot;T2&quot;.&quot;C1&quot;&gt;=1 AND &quot;T2&quot;.&quot;C1&quot;&lt;=20 AND &quot;T2&quot;.&quot;C1&quot;=&quot;V&quot;.&quot;C1&quot;

============
Plan Table
============
---------------------------------------+-----------------------------------+
&#124; Id  &#124; Operation            &#124; Name    &#124; Rows  &#124; Bytes &#124; Cost  &#124; Time      &#124;
---------------------------------------+-----------------------------------+
&#124; 0   &#124; SELECT STATEMENT     &#124;         &#124;       &#124;       &#124;    93 &#124;           &#124;
&#124; 1   &#124;  HASH JOIN           &#124;         &#124;     3 &#124;  6084 &#124;    93 &#124;  00:00:01 &#124;
&#124; 2   &#124;   TABLE ACCESS FULL  &#124; T2      &#124;     3 &#124;    39 &#124;    32 &#124;  00:00:01 &#124;
&#124; 3   &#124;   VIEW               &#124;         &#124;     6 &#124;   12K &#124;    60 &#124;  00:00:01 &#124;
&#124; 4   &#124;    TABLE ACCESS FULL &#124; T1      &#124;     6 &#124;   12K &#124;    60 &#124;  00:00:01 &#124;
---------------------------------------+-----------------------------------+
Predicate Information:
----------------------
1 - access(&quot;T2&quot;.&quot;C1&quot;=&quot;V&quot;.&quot;C1&quot;)
2 - filter((&quot;T2&quot;.&quot;C1&quot;&gt;=1 AND &quot;T2&quot;.&quot;C1&quot;&lt;=20))
4 - filter((&quot;C1&quot;&gt;=1 AND &quot;C1&quot;&lt;=20))

Dumping Hints
=============
  atom_hint=(@=00000000161B15C0 err=0 resol=1 used=0 token=880 org=1 lvl=3 txt=NO_PUSH_PRED (&quot;V&quot;) )
  atom_hint=(@=00000000161B1838 err=0 resol=1 used=1 token=876 org=1 lvl=3 txt=NO_MERGE (&quot;V&quot;) )
&lt;/pre&gt;


&lt;pre&gt;
ALTER SESSION SET TRACEFILE_IDENTIFIER=&#039;WATCH_TRANSFORM2&#039;; 
ALTER SESSION SET EVENTS &#039;10053 TRACE NAME CONTEXT FOREVER, LEVEL 1&#039;;

SELECT /*+ NO_MERGE(V) PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V,
  T2
WHERE
  T2.C1 BETWEEN 1 AND 20
  AND T2.C1=V.C1(+);

SELECT /*+ NO_MERGE(V) NO_PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V,
  T2
WHERE
  T2.C1 BETWEEN 1 AND 20
  AND T2.C1=V.C1(+);

ALTER SESSION SET EVENTS &#039;10053 TRACE NAME CONTEXT OFF&#039;;
&lt;/pre&gt;]]></description>
		<content:encoded><![CDATA[<p>Narendra,</p>
<p>Interesting points.  Let&#8217;s double-check the accurary of the statements:</p>
<p><a href="http://jonathanlewis.wordpress.com/2008/02/17/pushing-predicates-2/" rel="nofollow">http://jonathanlewis.wordpress.com/2008/02/17/pushing-predicates-2/</a><br />
<a href="http://www.jlcomp.demon.co.uk/push_pred.html" rel="nofollow">http://www.jlcomp.demon.co.uk/push_pred.html</a><br />
From the above links, PUSH_PRED and NO_PUSH_PRED hints are associated with the &#8220;join predicate pushdown (JPPD)&#8221; section of a 10053 trace file. The predicates that I was expecting to see generated are actually generated in the filter &#8220;push-down (FPD)&#8221; section (see the test case 10053 output below).</p>
<p>&#8212;</p>
<p><a href="http://download.oracle.com/docs/cd/E14072_01/server.112/e10592/queries003.htm" rel="nofollow">http://download.oracle.com/docs/cd/E14072_01/server.112/e10592/queries003.htm</a></p>
<blockquote><p>
Oracle processes hierarchical queries as follows:<br />
•A join, if present, is evaluated first, whether the join is specified in the FROM clause or with WHERE clause predicates.<br />
•The CONNECT BY condition is evaluated.<br />
•Any remaining WHERE clause predicates are evaluated.</p>
<p>Oracle then uses the information from these evaluations to form the hierarchy using the following steps:<br />
1.Oracle selects the root row(s) of the hierarchy—those rows that satisfy the START WITH condition.<br />
2.Oracle selects the child rows of each root row. Each child row must satisfy the condition of the CONNECT BY condition with respect to one of the root rows.<br />
3.Oracle selects successive generations of child rows. Oracle first selects the children of the rows returned in step 2, and then the children of those children, and so on. Oracle always selects children by evaluating the CONNECT BY condition with respect to a current parent row.<br />
4.If the query contains a WHERE clause without a join, then Oracle eliminates all rows from the hierarchy that do not satisfy the condition of the WHERE clause. Oracle evaluates this condition for each row individually, rather than removing all the children of a row that does not satisfy the condition.<br />
5.Oracle returns the rows in the order shown in Figure 9-1. In the diagram, children appear below their parents. For an explanation of hierarchical trees, see Figure 2-1, &#8220;Hierarchical Tree&#8221;.
</p></blockquote>
<p>It appears that your two points are valid.  Thank you for the correction.</p>
<p>Test case script:</p>
<pre>
CREATE TABLE T1 AS
SELECT
  ROWNUM C1,
  DBMS_RANDOM.STRING('A',20) C2,
  SYSDATE+ROWNUM/100 C3
FROM
  DUAL
CONNECT BY
  LEVEL&lt;=100000;

CREATE TABLE T2 AS
SELECT
  ROWNUM*2 C1,
  DBMS_RANDOM.STRING('A',20) C2,
  SYSDATE+ROWNUM/100 C3
FROM
  DUAL
CONNECT BY
  LEVEL&lt;=50000;
</pre>
<pre>
ALTER SESSION SET TRACEFILE_IDENTIFIER='WATCH_TRANSFORM'; 
ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT FOREVER, LEVEL 1';

SELECT /*+ NO_MERGE(V) PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V
WHERE
  V.C1 BETWEEN 1 AND 10;

SELECT /*+ NO_MERGE(V) NO_PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V
WHERE
  V.C1 BETWEEN 1 AND 10;

SELECT /*+ NO_MERGE(V) PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V,
  T2
WHERE
  T2.C1 BETWEEN 1 AND 20
  AND T2.C1=V.C1;

SELECT /*+ NO_MERGE(V) NO_PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V,
  T2
WHERE
  T2.C1 BETWEEN 1 AND 20
  AND T2.C1=V.C1;

ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT OFF';
</pre>
<p>Sections of the generated 10053 trace file:</p>
<pre>
----- Current SQL Statement for this session (sql_id=fxa990xn82j8u) -----
SELECT /*+ NO_MERGE(V) PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V
WHERE
  V.C1 BETWEEN 1 AND 10

JPPD:     JPPD bypassed: View has unsupported constructs.

**************************
Predicate Move-Around (PM)
**************************
PM:   Passed validity checks.
PM:   Pushed down predicate "T1"."C1"&gt;=1
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:   Pushed down predicate "T1"."C1"&lt;=10
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:     PM bypassed: checking.
query block SEL$1 (#0) unchanged
FPD: Considering simple filter push in query block SEL$1 (#0)
 ?? 
FPD: Considering simple filter push in query block SEL$2 (#0)
"T1"."C1"&gt;=1 AND "T1"."C1"&lt;=10
try to generate transitive predicate from check constraints for query block SEL$2 (#0)
finally: "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=10 AND 1&lt;=10
FPD:   transitive predicates are generated in query block SEL$2 (#0)
"T1"."C1"&gt;=1 AND "T1"."C1"&lt;=10 AND 1&lt;=10
apadrv-start sqlid=17197321763885761818

Final query after transformations:******* UNPARSED QUERY IS *******
SELECT /*+ PUSH_PRED ("V") NO_MERGE ("V") */ "V"."C1" "C1","V"."C2" "C2" FROM  
(SELECT "T1"."C1" "C1","T1"."C2" "C2" FROM "TESTUSER"."T1" "T1" WHERE "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=10 AND 1&lt;=10) "V"

============
Plan Table
============
--------------------------------------+-----------------------------------+
| Id  | Operation           | Name    | Rows  | Bytes | Cost  | Time      |
--------------------------------------+-----------------------------------+
| 0   | SELECT STATEMENT    |         |       |       |    60 |           |
| 1   |  VIEW               |         |     6 |   12K |    60 |  00:00:01 |
| 2   |   TABLE ACCESS FULL | T1      |     6 |   12K |    60 |  00:00:01 |
--------------------------------------+-----------------------------------+
Predicate Information:
----------------------
2 - filter(("C1"&gt;=1 AND "C1"&lt;=10))

Dumping Hints
=============
  atom_hint=(@=00000000161B15E0 err=0 resol=1 used=1 token=895 org=1 lvl=3 txt=PUSH_PRED ("V") )
  atom_hint=(@=00000000161B1858 err=0 resol=1 used=1 token=876 org=1 lvl=3 txt=NO_MERGE ("V") )
</pre>
<p>The above seems to indicate that the PUSH_PRED and NO_MERGE hints were both used, and we can see by the modified WHERE clause that the predicates present outside the inline view were </p>
<p>transferred inside the inline view (caused by &#8220;simple filter push&#8221;).</p>
<pre>
SELECT /*+ NO_MERGE(V) NO_PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V
WHERE
  V.C1 BETWEEN 1 AND 10

JPPD:     JPPD bypassed: View has unsupported constructs.

**************************
Predicate Move-Around (PM)
**************************
PM:   Passed validity checks.
PM:   Pushed down predicate "T1"."C1"&gt;=1
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:   Pushed down predicate "T1"."C1"&lt;=10
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:     PM bypassed: checking.
query block SEL$1 (#0) unchanged
FPD: Considering simple filter push in query block SEL$1 (#0)
 ?? 
FPD: Considering simple filter push in query block SEL$2 (#0)
"T1"."C1"&gt;=1 AND "T1"."C1"&lt;=10
try to generate transitive predicate from check constraints for query block SEL$2 (#0)
finally: "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=10 AND 1&lt;=10
FPD:   transitive predicates are generated in query block SEL$2 (#0)
"T1"."C1"&gt;=1 AND "T1"."C1"&lt;=10 AND 1&lt;=10
apadrv-start sqlid=3636309318118712829
 
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT /*+ NO_PUSH_PRED ("V") NO_MERGE ("V") */ "V"."C1" "C1","V"."C2" "C2" FROM  
(SELECT "T1"."C1" "C1","T1"."C2" "C2" FROM "TESTUSER"."T1" "T1" WHERE "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=10 AND 1&lt;=10) "V"

============
Plan Table
============
--------------------------------------+-----------------------------------+
| Id  | Operation           | Name    | Rows  | Bytes | Cost  | Time      |
--------------------------------------+-----------------------------------+
| 0   | SELECT STATEMENT    |         |       |       |    60 |           |
| 1   |  VIEW               |         |     6 |   12K |    60 |  00:00:01 |
| 2   |   TABLE ACCESS FULL | T1      |     6 |   12K |    60 |  00:00:01 |
--------------------------------------+-----------------------------------+
Predicate Information:
----------------------
2 - filter(("C1"&gt;=1 AND "C1"&lt;=10))
 
Dumping Hints
=============
  atom_hint=(@=00000000161B15D8 err=0 resol=1 used=0 token=880 org=1 lvl=3 txt=NO_PUSH_PRED ("V") )
  atom_hint=(@=00000000161B1850 err=0 resol=1 used=1 token=876 org=1 lvl=3 txt=NO_MERGE ("V") )
</pre>
<p>The above seems to indicate that the NO_PUSH_PRED hint was NOT used and NO_MERGE hints was used, and we can see by the modified WHERE clause that the predicates present outside the inline </p>
<p>view were transferred inside the inline view.</p>
<pre>
SELECT /*+ NO_MERGE(V) PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V,
  T2
WHERE
  T2.C1 BETWEEN 1 AND 20
  AND T2.C1=V.C1

JPPD:     JPPD bypassed: View has unsupported constructs.

**************************
Predicate Move-Around (PM)
**************************
PM:   Passed validity checks.
PM: Added transitive pred "V"."C1"&gt;=1
 in query block SEL$1 (#0)
PM: Added transitive pred "V"."C1"&lt;=20
 in query block SEL$1 (#0)
PM:   Pushed down predicate "T1"."C1"&gt;=1
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:   Pushed down predicate "T1"."C1"&lt;=20
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:     PM bypassed: checking.
query block SEL$1 (#0) unchanged
FPD: Considering simple filter push in query block SEL$1 (#0)
"T2"."C1"&gt;=1 AND "T2"."C1"&lt;=20 AND "T2"."C1"="V"."C1"
try to generate transitive predicate from check constraints for query block SEL$1 (#0)
finally: "T2"."C1"&gt;=1 AND "T2"."C1"&lt;=20 AND "T2"."C1"="V"."C1" AND 1&lt;=20 AND "V"."C1"&gt;=1 AND "V"."C1"&lt;=20

FPD:   transitive predicates are generated in query block SEL$1 (#0)
"T2"."C1"&gt;=1 AND "T2"."C1"&lt;=20 AND "T2"."C1"="V"."C1" AND 1&lt;=20 AND "V"."C1"&gt;=1 AND "V"."C1"&lt;=20
JPPD:     JPPD bypassed: View not on right-side of outer-join.         &lt;======================
FPD:   Following are pushed to where clause of query block SEL$2 (#0)
1&lt;=20 AND "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=20
FPD: Considering simple filter push in query block SEL$2 (#0)
"T1"."C1"&gt;=1 AND "T1"."C1"&lt;=20 AND 1&lt;=20 AND "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=20
try to generate transitive predicate from check constraints for query block SEL$2 (#0)
finally: "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=20 AND 1&lt;=20 AND "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=20
 
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT /*+ PUSH_PRED ("V") NO_MERGE ("V") */ "V"."C1" "C1","V"."C2" "C2" FROM  
(SELECT "T1"."C1" "C1","T1"."C2" "C2" FROM "TESTUSER"."T1" "T1" WHERE "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=20 AND 1&lt;=20 AND "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=20) "V",
"TESTUSER"."T2" "T2" WHERE "T2"."C1"&gt;=1 AND "T2"."C1"&lt;=20 AND "T2"."C1"="V"."C1"

============
Plan Table
============
---------------------------------------+-----------------------------------+
| Id  | Operation            | Name    | Rows  | Bytes | Cost  | Time      |
---------------------------------------+-----------------------------------+
| 0   | SELECT STATEMENT     |         |       |       |    93 |           |
| 1   |  HASH JOIN           |         |     3 |  6084 |    93 |  00:00:01 |
| 2   |   TABLE ACCESS FULL  | T2      |     3 |    39 |    32 |  00:00:01 |
| 3   |   VIEW               |         |     6 |   12K |    60 |  00:00:01 |
| 4   |    TABLE ACCESS FULL | T1      |     6 |   12K |    60 |  00:00:01 |
---------------------------------------+-----------------------------------+
Predicate Information:
----------------------
1 - access("T2"."C1"="V"."C1")
2 - filter(("T2"."C1"&gt;=1 AND "T2"."C1"&lt;=20))
4 - filter(("C1"&gt;=1 AND "C1"&lt;=20))
 
Dumping Hints
=============
  atom_hint=(@=00000000161B15C8 err=0 resol=1 used=1 token=895 org=1 lvl=3 txt=PUSH_PRED ("V") )
  atom_hint=(@=00000000161B1840 err=0 resol=1 used=1 token=876 org=1 lvl=3 txt=NO_MERGE ("V") )
</pre>
<p>The above seems to indicate that the PUSH_PRED and NO_MERGE hints were both used, and we can see by the modified WHERE clause that the predicates present outside the inline view were </p>
<p>transferred inside the inline view (twice!).</p>
<pre>
SELECT /*+ NO_MERGE(V) NO_PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V,
  T2
WHERE
  T2.C1 BETWEEN 1 AND 20
  AND T2.C1=V.C1

JPPD:     JPPD bypassed: View has unsupported constructs.

**************************
Predicate Move-Around (PM)
**************************
PM:   Passed validity checks.
PM: Added transitive pred "V"."C1"&gt;=1
 in query block SEL$1 (#0)
PM: Added transitive pred "V"."C1"&lt;=20
 in query block SEL$1 (#0)
PM:   Pushed down predicate "T1"."C1"&gt;=1
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:   Pushed down predicate "T1"."C1"&lt;=20
 from query block SEL$1 (#0) to query block SEL$2 (#0)
PM:     PM bypassed: checking.
query block SEL$1 (#0) unchanged
FPD: Considering simple filter push in query block SEL$1 (#0)
"T2"."C1"&gt;=1 AND "T2"."C1"&lt;=20 AND "T2"."C1"="V"."C1"
try to generate transitive predicate from check constraints for query block SEL$1 (#0)
finally: "T2"."C1"&gt;=1 AND "T2"."C1"&lt;=20 AND "T2"."C1"="V"."C1" AND 1&lt;=20 AND "V"."C1"&gt;=1 AND "V"."C1"&lt;=20

FPD:   transitive predicates are generated in query block SEL$1 (#0)
"T2"."C1"&gt;=1 AND "T2"."C1"&lt;=20 AND "T2"."C1"="V"."C1" AND 1&lt;=20 AND "V"."C1"&gt;=1 AND "V"."C1"&lt;=20
JPPD:     JPPD bypassed: View not on right-side of outer-join.
FPD:   Following are pushed to where clause of query block SEL$2 (#0)
1&lt;=20 AND "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=20
FPD: Considering simple filter push in query block SEL$2 (#0)
"T1"."C1"&gt;=1 AND "T1"."C1"&lt;=20 AND 1&lt;=20 AND "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=20
try to generate transitive predicate from check constraints for query block SEL$2 (#0)
finally: "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=20 AND 1&lt;=20 AND "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=20

Final query after transformations:******* UNPARSED QUERY IS *******
SELECT /*+ NO_PUSH_PRED ("V") NO_MERGE ("V") */ "V"."C1" "C1","V"."C2" "C2" FROM  
(SELECT "T1"."C1" "C1","T1"."C2" "C2" FROM "TESTUSER"."T1" "T1" WHERE "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=20 AND 1&lt;=20 AND "T1"."C1"&gt;=1 AND "T1"."C1"&lt;=20) "V",
"TESTUSER"."T2" "T2" WHERE "T2"."C1"&gt;=1 AND "T2"."C1"&lt;=20 AND "T2"."C1"="V"."C1"

============
Plan Table
============
---------------------------------------+-----------------------------------+
| Id  | Operation            | Name    | Rows  | Bytes | Cost  | Time      |
---------------------------------------+-----------------------------------+
| 0   | SELECT STATEMENT     |         |       |       |    93 |           |
| 1   |  HASH JOIN           |         |     3 |  6084 |    93 |  00:00:01 |
| 2   |   TABLE ACCESS FULL  | T2      |     3 |    39 |    32 |  00:00:01 |
| 3   |   VIEW               |         |     6 |   12K |    60 |  00:00:01 |
| 4   |    TABLE ACCESS FULL | T1      |     6 |   12K |    60 |  00:00:01 |
---------------------------------------+-----------------------------------+
Predicate Information:
----------------------
1 - access("T2"."C1"="V"."C1")
2 - filter(("T2"."C1"&gt;=1 AND "T2"."C1"&lt;=20))
4 - filter(("C1"&gt;=1 AND "C1"&lt;=20))

Dumping Hints
=============
  atom_hint=(@=00000000161B15C0 err=0 resol=1 used=0 token=880 org=1 lvl=3 txt=NO_PUSH_PRED ("V") )
  atom_hint=(@=00000000161B1838 err=0 resol=1 used=1 token=876 org=1 lvl=3 txt=NO_MERGE ("V") )
</pre>
<pre>
ALTER SESSION SET TRACEFILE_IDENTIFIER='WATCH_TRANSFORM2'; 
ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT FOREVER, LEVEL 1';

SELECT /*+ NO_MERGE(V) PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V,
  T2
WHERE
  T2.C1 BETWEEN 1 AND 20
  AND T2.C1=V.C1(+);

SELECT /*+ NO_MERGE(V) NO_PUSH_PRED(V) */
  V.C1,
  V.C2
FROM
  (SELECT
     C1,
     C2,
     C3
  FROM
    T1) V,
  T2
WHERE
  T2.C1 BETWEEN 1 AND 20
  AND T2.C1=V.C1(+);

ALTER SESSION SET EVENTS '10053 TRACE NAME CONTEXT OFF';
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Narendra</title>
		<link>http://hoopercharles.wordpress.com/2011/05/26/row-values-to-comma-separated-lists-an-overly-complicated-use-case-example/#comment-3244</link>
		<dc:creator><![CDATA[Narendra]]></dc:creator>
		<pubDate>Fri, 27 May 2011 13:45:42 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=4873#comment-3244</guid>
		<description><![CDATA[Charles,

Let me first clarify that I am not trying to argue against the use of LISTAGG function. I love it and I would myself use it whenever possible. It just simplifies many things.
However, I guess there are a couple of things I would like to point out
1) The PUSH_PRED hint is applicable to only join predicates (&lt;i&gt;why didn&#039;t they call it PUSH_JOIN_PRED to avoid confusion?&lt;/i&gt;) as mentioned &lt;a href=&quot;http://download.oracle.com/docs/cd/E11882_01/server.112/e17118/sql_elements006.htm#SQLRF50907&quot; rel=&quot;nofollow&quot;&gt; here&lt;/a&gt;. So it won&#039;t make any difference to your query.
2) When you use SYS_CONNECT_BY_PATH to aggregate the string, you are effectively using hierarchical query feature of Oracle. One of the &quot;features&quot; of hierarchical query
is oracle applies any WHERE predicates &lt;b&gt;AFTER&lt;/b&gt; it builds the entire hierarchy (using the CONNECT BY...START WITH clauses). This, combined with merging (or not) of view
in the main query, causes the WHERE predicate to be applied quite late in the query execution.
Following is my test-case which explains (??) the above point (unless, of course, if I have missed something obvious)
&lt;pre&gt;
SQL&gt; select * from v$version ;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE	11.2.0.1.0	Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

SQL&gt; set lines 171 pages 999 arrays 151
SQL&gt; create table t3
   (
   txid   ,
   month  ,
   item_cd,
   qty
   ) nologging 
as
select
   floor(rownum/5),
   floor(rownum/20),
   floor(rownum/10),
   floor(rownum/5)
from
   dual
connect by
   level  set autotrace traceonly explain
SQL&gt; select txid, month, item_cd, qty, Row_Number() Over (Partition By txid Order By 1) from t3 where item_cd = 0 ;

Execution Plan
----------------------------------------------------------
Plan hash value: 1976707564

---------------------------------------------------------------------------
&#124; Id  &#124; Operation	   &#124; Name &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time	  &#124;
---------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT   &#124;	  &#124;	9 &#124;   468 &#124;    11  (10)&#124; 00:00:01 &#124;
&#124;   1 &#124;  WINDOW SORT	   &#124;	  &#124;	9 &#124;   468 &#124;    11  (10)&#124; 00:00:01 &#124;
&#124;*  2 &#124;   TABLE ACCESS FULL&#124; T3   &#124;	9 &#124;   468 &#124;    10   (0)&#124; 00:00:01 &#124;
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(&quot;ITEM_CD&quot;=0)

Note
-----
   - dynamic sampling used for this statement (level=2)

SQL&gt; select txid, month, item_cd, qty, rn from (select txid, month, item_cd, qty, Row_Number() Over (Partition By txid Order By 1) rn from t3) where item_cd = 0 ;

Execution Plan
----------------------------------------------------------
Plan hash value: 3729804300

------------------------------------------------------------------------------------
&#124; Id  &#124; Operation	    &#124; Name &#124; Rows  &#124; Bytes &#124;TempSpc&#124; Cost (%CPU)&#124; Time	   &#124;
------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT    &#124;	   &#124; 10000 &#124;   634K&#124;	   &#124;   144   (2)&#124; 00:00:02 &#124;
&#124;*  1 &#124;  VIEW		    &#124;	   &#124; 10000 &#124;   634K&#124;	   &#124;   144   (2)&#124; 00:00:02 &#124;
&#124;   2 &#124;   WINDOW SORT	    &#124;	   &#124; 10000 &#124;   507K&#124;   640K&#124;   144   (2)&#124; 00:00:02 &#124;
&#124;   3 &#124;    TABLE ACCESS FULL&#124; T3   &#124; 10000 &#124;   507K&#124;	   &#124;	10   (0)&#124; 00:00:01 &#124;
------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(&quot;ITEM_CD&quot;=0)

Note
-----
   - dynamic sampling used for this statement (level=2)

SQL&gt; select txid, month, item_cd, qty, rn from (select txid, month, item_cd, qty, Row_Number() Over (Partition By txid, item_cd Order By 1) rn from t3) where item_cd = 0 ;

Execution Plan
----------------------------------------------------------
Plan hash value: 3729804300

----------------------------------------------------------------------------
&#124; Id  &#124; Operation	    &#124; Name &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time	   &#124;
----------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT    &#124;	   &#124;	 9 &#124;   585 &#124;	11  (10)&#124; 00:00:01 &#124;
&#124;   1 &#124;  VIEW		    &#124;	   &#124;	 9 &#124;   585 &#124;	11  (10)&#124; 00:00:01 &#124;
&#124;   2 &#124;   WINDOW SORT	    &#124;	   &#124;	 9 &#124;   468 &#124;	11  (10)&#124; 00:00:01 &#124;
&#124;*  3 &#124;    TABLE ACCESS FULL&#124; T3   &#124;	 9 &#124;   468 &#124;	10   (0)&#124; 00:00:01 &#124;
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter(&quot;ITEM_CD&quot;=0)

Note
-----
   - dynamic sampling used for this statement (level=2)

SQL&gt; SELECT
  MAX(REPLACE(SUBSTR(SYS_CONNECT_BY_PATH(TO_CHAR(QTY),&#039;,&#039;),2),&#039;,&#039;,CHR(13)&#124;&#124;CHR(10))) LISTING
FROM
(select txid, month, item_cd, qty, Row_Number() Over (Partition By txid, item_cd Order By 1) rn from t3) V
WHERE item_cd = 0
CONNECT BY PRIOR
  RN = RN-1
START WITH
  RN = 1;
  2    3    4    5    6    7    8    9  
Execution Plan
----------------------------------------------------------
Plan hash value: 3401893796

--------------------------------------------------------------------------------------------------
&#124; Id  &#124; Operation				  &#124; Name &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time	 &#124;
--------------------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT			  &#124;	 &#124;     1 &#124;    39 &#124;    13  (24)&#124; 00:00:01 &#124;
&#124;   1 &#124;  SORT AGGREGATE 			  &#124;	 &#124;     1 &#124;    39 &#124;	      &#124; 	 &#124;
&#124;*  2 &#124;   FILTER				  &#124;	 &#124;	 &#124;	 &#124;	      &#124; 	 &#124;
&#124;*  3 &#124;    CONNECT BY NO FILTERING WITH START-WITH&#124;	 &#124;	 &#124;	 &#124;	      &#124; 	 &#124;
&#124;   4 &#124;     VIEW				  &#124;	 &#124; 10000 &#124;   380K&#124;    12  (17)&#124; 00:00:01 &#124;
&#124;   5 &#124;      WINDOW SORT			  &#124;	 &#124; 10000 &#124;   380K&#124;    12  (17)&#124; 00:00:01 &#124;
&#124;   6 &#124;       TABLE ACCESS FULL 		  &#124; T3	 &#124; 10000 &#124;   380K&#124;    10   (0)&#124; 00:00:01 &#124;
--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(&quot;ITEM_CD&quot;=0)
   3 - access(&quot;RN&quot;-1=PRIOR &quot;RN&quot;)
       filter(&quot;RN&quot;=1)

Note
-----
   - dynamic sampling used for this statement (level=2)

SQL&gt; SELECT
  MAX(REPLACE(SUBSTR(SYS_CONNECT_BY_PATH(TO_CHAR(QTY),&#039;,&#039;),2),&#039;,&#039;,CHR(13)&#124;&#124;CHR(10))) LISTING
FROM 
(SELECT /*+ NO_MERGE */ txid, month, item_cd, qty, rn
  FROM (select txid, month, item_cd, qty, Row_Number() Over (Partition By txid, item_cd Order By 1) rn from t3)
 WHERE item_cd = 0) V
CONNECT BY PRIOR
  RN = RN-1
START WITH
  RN = 1;
  2    3    4    5    6    7    8    9   10  
Execution Plan
----------------------------------------------------------
Plan hash value: 2047232111

-------------------------------------------------------------------------------------------------
&#124; Id  &#124; Operation				 &#124; Name &#124; Rows	&#124; Bytes &#124; Cost (%CPU)&#124; Time	&#124;
-------------------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT			 &#124;	&#124;     1 &#124;    26 &#124;    12  (17)&#124; 00:00:01 &#124;
&#124;   1 &#124;  SORT AGGREGATE 			 &#124;	&#124;     1 &#124;    26 &#124;	     &#124;		&#124;
&#124;*  2 &#124;   CONNECT BY NO FILTERING WITH START-WITH&#124;	&#124;	&#124;	&#124;	     &#124;		&#124;
&#124;   3 &#124;    VIEW 				 &#124;	&#124;     9 &#124;   234 &#124;    11  (10)&#124; 00:00:01 &#124;
&#124;   4 &#124;     VIEW				 &#124;	&#124;     9 &#124;   351 &#124;    11  (10)&#124; 00:00:01 &#124;
&#124;   5 &#124;      WINDOW SORT			 &#124;	&#124;     9 &#124;   351 &#124;    11  (10)&#124; 00:00:01 &#124;
&#124;*  6 &#124;       TABLE ACCESS FULL 		 &#124; T3	&#124;     9 &#124;   351 &#124;    10   (0)&#124; 00:00:01 &#124;
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access(&quot;RN&quot;-1=PRIOR &quot;RN&quot;)
       filter(&quot;RN&quot;=1)
   6 - filter(&quot;ITEM_CD&quot;=0)

Note
-----
   - dynamic sampling used for this statement (level=2)
&lt;/pre&gt;]]></description>
		<content:encoded><![CDATA[<p>Charles,</p>
<p>Let me first clarify that I am not trying to argue against the use of LISTAGG function. I love it and I would myself use it whenever possible. It just simplifies many things.<br />
However, I guess there are a couple of things I would like to point out<br />
1) The PUSH_PRED hint is applicable to only join predicates (<i>why didn&#8217;t they call it PUSH_JOIN_PRED to avoid confusion?</i>) as mentioned <a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e17118/sql_elements006.htm#SQLRF50907" rel="nofollow"> here</a>. So it won&#8217;t make any difference to your query.<br />
2) When you use SYS_CONNECT_BY_PATH to aggregate the string, you are effectively using hierarchical query feature of Oracle. One of the &#8220;features&#8221; of hierarchical query<br />
is oracle applies any WHERE predicates <b>AFTER</b> it builds the entire hierarchy (using the CONNECT BY&#8230;START WITH clauses). This, combined with merging (or not) of view<br />
in the main query, causes the WHERE predicate to be applied quite late in the query execution.<br />
Following is my test-case which explains (??) the above point (unless, of course, if I have missed something obvious)</p>
<pre>
SQL&gt; select * from v$version ;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE	11.2.0.1.0	Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

SQL&gt; set lines 171 pages 999 arrays 151
SQL&gt; create table t3
   (
   txid   ,
   month  ,
   item_cd,
   qty
   ) nologging 
as
select
   floor(rownum/5),
   floor(rownum/20),
   floor(rownum/10),
   floor(rownum/5)
from
   dual
connect by
   level  set autotrace traceonly explain
SQL&gt; select txid, month, item_cd, qty, Row_Number() Over (Partition By txid Order By 1) from t3 where item_cd = 0 ;

Execution Plan
----------------------------------------------------------
Plan hash value: 1976707564

---------------------------------------------------------------------------
| Id  | Operation	   | Name | Rows  | Bytes | Cost (%CPU)| Time	  |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |	  |	9 |   468 |    11  (10)| 00:00:01 |
|   1 |  WINDOW SORT	   |	  |	9 |   468 |    11  (10)| 00:00:01 |
|*  2 |   TABLE ACCESS FULL| T3   |	9 |   468 |    10   (0)| 00:00:01 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("ITEM_CD"=0)

Note
-----
   - dynamic sampling used for this statement (level=2)

SQL&gt; select txid, month, item_cd, qty, rn from (select txid, month, item_cd, qty, Row_Number() Over (Partition By txid Order By 1) rn from t3) where item_cd = 0 ;

Execution Plan
----------------------------------------------------------
Plan hash value: 3729804300

------------------------------------------------------------------------------------
| Id  | Operation	    | Name | Rows  | Bytes |TempSpc| Cost (%CPU)| Time	   |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |	   | 10000 |   634K|	   |   144   (2)| 00:00:02 |
|*  1 |  VIEW		    |	   | 10000 |   634K|	   |   144   (2)| 00:00:02 |
|   2 |   WINDOW SORT	    |	   | 10000 |   507K|   640K|   144   (2)| 00:00:02 |
|   3 |    TABLE ACCESS FULL| T3   | 10000 |   507K|	   |	10   (0)| 00:00:01 |
------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("ITEM_CD"=0)

Note
-----
   - dynamic sampling used for this statement (level=2)

SQL&gt; select txid, month, item_cd, qty, rn from (select txid, month, item_cd, qty, Row_Number() Over (Partition By txid, item_cd Order By 1) rn from t3) where item_cd = 0 ;

Execution Plan
----------------------------------------------------------
Plan hash value: 3729804300

----------------------------------------------------------------------------
| Id  | Operation	    | Name | Rows  | Bytes | Cost (%CPU)| Time	   |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |	   |	 9 |   585 |	11  (10)| 00:00:01 |
|   1 |  VIEW		    |	   |	 9 |   585 |	11  (10)| 00:00:01 |
|   2 |   WINDOW SORT	    |	   |	 9 |   468 |	11  (10)| 00:00:01 |
|*  3 |    TABLE ACCESS FULL| T3   |	 9 |   468 |	10   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("ITEM_CD"=0)

Note
-----
   - dynamic sampling used for this statement (level=2)

SQL&gt; SELECT
  MAX(REPLACE(SUBSTR(SYS_CONNECT_BY_PATH(TO_CHAR(QTY),','),2),',',CHR(13)||CHR(10))) LISTING
FROM
(select txid, month, item_cd, qty, Row_Number() Over (Partition By txid, item_cd Order By 1) rn from t3) V
WHERE item_cd = 0
CONNECT BY PRIOR
  RN = RN-1
START WITH
  RN = 1;
  2    3    4    5    6    7    8    9  
Execution Plan
----------------------------------------------------------
Plan hash value: 3401893796

--------------------------------------------------------------------------------------------------
| Id  | Operation				  | Name | Rows  | Bytes | Cost (%CPU)| Time	 |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT			  |	 |     1 |    39 |    13  (24)| 00:00:01 |
|   1 |  SORT AGGREGATE 			  |	 |     1 |    39 |	      | 	 |
|*  2 |   FILTER				  |	 |	 |	 |	      | 	 |
|*  3 |    CONNECT BY NO FILTERING WITH START-WITH|	 |	 |	 |	      | 	 |
|   4 |     VIEW				  |	 | 10000 |   380K|    12  (17)| 00:00:01 |
|   5 |      WINDOW SORT			  |	 | 10000 |   380K|    12  (17)| 00:00:01 |
|   6 |       TABLE ACCESS FULL 		  | T3	 | 10000 |   380K|    10   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("ITEM_CD"=0)
   3 - access("RN"-1=PRIOR "RN")
       filter("RN"=1)

Note
-----
   - dynamic sampling used for this statement (level=2)

SQL&gt; SELECT
  MAX(REPLACE(SUBSTR(SYS_CONNECT_BY_PATH(TO_CHAR(QTY),','),2),',',CHR(13)||CHR(10))) LISTING
FROM 
(SELECT /*+ NO_MERGE */ txid, month, item_cd, qty, rn
  FROM (select txid, month, item_cd, qty, Row_Number() Over (Partition By txid, item_cd Order By 1) rn from t3)
 WHERE item_cd = 0) V
CONNECT BY PRIOR
  RN = RN-1
START WITH
  RN = 1;
  2    3    4    5    6    7    8    9   10  
Execution Plan
----------------------------------------------------------
Plan hash value: 2047232111

-------------------------------------------------------------------------------------------------
| Id  | Operation				 | Name | Rows	| Bytes | Cost (%CPU)| Time	|
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT			 |	|     1 |    26 |    12  (17)| 00:00:01 |
|   1 |  SORT AGGREGATE 			 |	|     1 |    26 |	     |		|
|*  2 |   CONNECT BY NO FILTERING WITH START-WITH|	|	|	|	     |		|
|   3 |    VIEW 				 |	|     9 |   234 |    11  (10)| 00:00:01 |
|   4 |     VIEW				 |	|     9 |   351 |    11  (10)| 00:00:01 |
|   5 |      WINDOW SORT			 |	|     9 |   351 |    11  (10)| 00:00:01 |
|*  6 |       TABLE ACCESS FULL 		 | T3	|     9 |   351 |    10   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("RN"-1=PRIOR "RN")
       filter("RN"=1)
   6 - filter("ITEM_CD"=0)

Note
-----
   - dynamic sampling used for this statement (level=2)
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Log Buffer #222, A Carnival of the Vanities for DBAs &#124; The Pythian Blog</title>
		<link>http://hoopercharles.wordpress.com/2011/05/26/row-values-to-comma-separated-lists-an-overly-complicated-use-case-example/#comment-3242</link>
		<dc:creator><![CDATA[Log Buffer #222, A Carnival of the Vanities for DBAs &#124; The Pythian Blog]]></dc:creator>
		<pubDate>Fri, 27 May 2011 12:34:29 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=4873#comment-3242</guid>
		<description><![CDATA[[...] Charles Hooper blogs about an Overly Complicated Use Case Example regarding Row Values to Comma Separated Lists. [...]]]></description>
		<content:encoded><![CDATA[<p>[...] Charles Hooper blogs about an Overly Complicated Use Case Example regarding Row Values to Comma Separated Lists. [...]</p>
]]></content:encoded>
	</item>
</channel>
</rss>
