|
http://structureddata.org/2008/0 ... -and-lateral-views/
从这文章得到了启发,虽然他只是描述了这几个查询的不同和转换,没有明确说明ORACLE不去做这个判断的原因。
个人认为是:- Query block (08C058D4) before join elimination:
- SQL:******* UNPARSED QUERY IS *******
- SELECT "TMP1"."ID" "QCSJ_C000000000300000","TMP1"."FEE" "QCSJ_C000000000300002","from$_subquery$_004"."ID_1" "ID","from$_subquery$_004"."FEE_0" "FEE" FROM "BI"."TMP1" "TMP1", LATERAL( (SELECT "TMP2"."FEE" "FEE_0","TMP2"."ID" "ID_1" FROM "BI"."TMP2" "TMP2" WHERE "TMP1"."ID"="TMP2"."ID" AND ("TMP2"."FEE"=20 OR "TMP2"."FEE"=30)))(+) "from$_subquery$_004"
- Query block (08C058D4) unchanged
- CVM: Merging SPJ view SEL$2 (#0) into SEL$3 (#0)
- Query block (08C0A6B4) before join elimination:
- SQL:******* UNPARSED QUERY IS *******
- SELECT COUNT(*) "COUNT(*)" FROM "BI"."TMP1" "TMP1", LATERAL( (SELECT "TMP2"."FEE" "FEE_0","TMP2"."ID" "ID_1" FROM "BI"."TMP2" "TMP2" WHERE "TMP1"."ID"="TMP2"."ID" AND ("TMP2"."FEE"=20 OR "TMP2"."FEE"=30)))(+) "from$_subquery$_004"
- Query block (08C0A6B4) unchanged
复制代码
或许因为OR存在,而为了维护A表的完整性,把QUERY提在JOIN前面,所以就只能做NEST LOOP。
如果是用HASH JOIN的话,假设他把(“TMP2"."FEE"=20 OR "TMP2"."FEE"=30)做为过滤器谓词。那么它必须是(“TMP2"."FEE"(+)=20 OR "TMP2"."FEE " (+)=30) 这种形式,但是我在两个版本的试验里,发现这个是触发ORA-01719: outer join operator (+) not allowed in operand of OR or IN 错误的。
而这句:
- select * from tmp1 left join tmp2 on tmp1.id =tmp2.id and tmp1.fee =50
复制代码
因为 连接条件是TMP1表的FEE列限定值50,但其实它还需要起出TMP1表的其它值,只不过和TMP2关联的时候都为空。
所以这个语句也不能使用HASH JOIN,因为用HASH JOIN的话,同级别的过滤器谓词总是在访问谓词前执行。
它必须维护TMP1表的完整性。 |
|