我可以将包含INNER JOIN的子查询转换为LEFT JOIN,还是以其他方式展平?

问题描述

仍在学习Oracle SQL,所以我会尽力清楚地说明这一点。

在下面,我使用带有子选择的NOT EXISTS过滤掉数据,但是如果可能的话,我需要将其转换为联接。我以为这会涉及到LEFT JOIN,但是子选择中的其他INNER JOIN却使我绊倒了。

SELECT * 
FROM   table1
INNER JOIN table2
ON     table1.user_id = table2.user_id
AND NOT EXISTS (
           SELECT 1
           FROM   table3
           INNER JOIN table4
           ON     table4.event_id = table3.event_id
           WHERE  table3.status_id = table2.status_id
)

如何在不依赖子选择的情况下检索完全相同的结果?

解决方法

not exists和子查询是完成此任务的正确工具。

我想您要记住的是将其重写为两个LEFT JOIN和一个WHERE子句,以便仅对不匹配的记录进行过滤:

SELECT t1.*,t2.*
FROM   table1 t1
INNER JOIN table2 t2 ON t1.user_id = t2.user_id
LEFT JOIN  table3 t2 ON t3.status_id = t2.status_id
LEFT JOIN  table4 t4 ON t4.event_id = t3.event_id
WHERE t4.event_id IS NULL

但这并不等同于原始记录:如果一条记录在tabl3中有两个匹配项,而在table4中没有任何匹配项,那么结果集中将出现重复项。

这是一种愚蠢的解决方法,但是上述政策是否允许横向加入?

SELECT t1.*,t2.*
FROM   table1 t1
INNER JOIN table2 t2 ON t1.user_id = t2.user_id
OUTER APPLY (
    SELECT 1 flag
    FROM table3 t3
    INNER JOIN table4 ON t4.event_id = t3.event_id
    WHERE  t3.status_id = t2.status_id
) x 
WHERE x.flag IS NULL
,

这是反连接的非常简单的示例:

SELECT table1.*,table2.* 
FROM   table1
INNER JOIN table2
    ON     table1.user_id = table2.user_id
left JOIN(
           SELECT distinct table3.status_id
           FROM   table3
           INNER JOIN table4
           ON     table4.event_id = table3.event_id
    ) t3
    ON t3.status_id = table2.status_id
where t3.status_id is null;

如果Oracle优化器认为这样的转换更优化,那么它会为您自己进行转换。

,

使用括号的另一种方法:

select *
from   table1
       join table2
            on  table2.user_id = table1.user_id
       left join ( table3 join table4 on table4.event_id = table3.event_id ) 
            on  table3.status_id = table2.status_id
where  table4.event_id is null;

我没有您的数据,因此无法正确测试。如果table3 / table4联接为每个table1 / table2返回多行,可能会出现问题,因为这样您将获得比原始查询更多的行。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...