在 Oracle 中,这是带有过滤器的交叉连接还是内部连接?
Posted
技术标签:
【中文标题】在 Oracle 中,这是带有过滤器的交叉连接还是内部连接?【英文标题】:In Oracle, is this a cross join with a filter or a inner join? 【发布时间】:2022-01-12 22:11:31 【问题描述】:我在一些遗留的 sql 代码中遇到了这个问题,我想知道它是如何“在幕后”工作的。在下面的示例中,sql 引擎是将其视为带有过滤器的交叉连接还是“LIKE”关键字上的常规内部连接?
Select
t1.col1,
t2.col2
From
table1 t1,
table2 t2
Where t1.approved IS NULL
AND UPPER(NVL(t1.team, '%')) LIKE UPPER(NVL(t2.TEAM, '%'))
;
【问题讨论】:
是的,那是 1989 年的旧连接语法。它被称为“逗号分隔表”,现在非常不鼓励使用。INNER JOIN
是笛卡尔积的子集,其中输出仅包含满足连接谓词的那些行。这种连接的正式定义与笛卡尔积上的过滤器相同:select * from A join B on P(a,b) = [(a,b) : a ∈ A, b ∈ B, P(a,b) = 1]
。 explain plan
可以看到幕后发生的事情
我想更大的问题是为什么这不是 Oracle 中的内部联接? Select t1.col1, t2.col2 From table1 t1, table2 t2 Where t1.approved IS NULL AND UPPER('%') LIKE UPPER('%') ;它们导致不同的解释计划。
这不是内部联接,因为您没有引用两个表中的列。但是如果你在表名之间显式地放置一个inner join
文本,由于同样的原因和上面提到的定义,它不会变成一个内连接。这只是一个约定,您也可以通过在右表的列上应用任何比较来将显式 left join
转换为 inner
。
【参考方案1】:
交叉连接是完整的笛卡尔积。它导致两个表之间所有可能的组合。 如果过滤器引用两个表的列,则与过滤器的交叉连接可以是内部连接。 您的 SQL 肯定是内连接,因为它不是笛卡尔积并引用两个表的列。
您可以使用各种形式的内连接,例如
where substr(t1.col1, 1, 2) = t2.col2
where t1.col1 between t2.col1 and t2.col2
【讨论】:
【参考方案2】:实际上是INNER JOIN
:
SELECT t1.col1,
t2.col2
FROM table1 t1
INNER JOIN table2 t2
ON ( NVL(UPPER(t1.team), '%') LIKE UPPER(t2.team)
OR t2.team IS NULL)
WHERE t1.approved IS NULL;
【讨论】:
【参考方案3】:如果您想了解它是如何“在幕后”工作的,请运行一个解释计划。
Oracle 优化器在实际解析查询时会将查询重写为不同的形式。例如,我刚刚运行了一个测试,所有这 3 个查询:
select *
from table1 t1, table2 t2
where nvl(t1.team,'%') like nvl(t2.team, '%');
select *
from table1 t1
inner join table2 t2
on nvl(t1.team,'%') like nvl(t2.team, '%');
select *
from table1 t1
cross join table2 t2
where nvl(t1.team,'%') like nvl(t2.team, '%');
在我的环境中被翻译成同样的解释计划:
SELECT STATEMENT FIRST_ROWS Cost: 13 Bytes: 437,265 Cardinality: 1,845
3 NESTED LOOPS Cost: 13 Bytes: 437,265 Cardinality: 1,845
1 TABLE ACCESS FULL TABLE MYSCHEMA.TABLE1 Cost: 2 Bytes: 36,162 Cardinality: 369
2 TABLE ACCESS FULL TABLE MYSCHEMA.TABLE2 Cost: 11 Bytes: 256,455 Cardinality: 1,845
这意味着就 Oracle 而言,考虑到特定的表、行数和可用的统计信息,这 3 个查询是相同的。在大多数情况下,它们在逻辑上是等价的。
但是,这是一个简单的查询。如果您开始添加更多 WHERE 条件,或者表中的数据结构不同,或者如果您有索引,优化器可能会选择不同的计划,并且查询可能会执行不同的操作。
【讨论】:
以上是关于在 Oracle 中,这是带有过滤器的交叉连接还是内部连接?的主要内容,如果未能解决你的问题,请参考以下文章
[Oracle]多表连接技术-交叉连接非等值连接等值连接外连接