关于非相关子查询改写经验

1、问题

最近又又又再项目中遇到这样奇奇怪怪的写法

c 复制代码
select count(1)
  from t1
 where exists (select 1
          from (select case t1.state when 1 
          then sum(sum(t3.ll*0.5)+nvl(max(t2.ll),0)) over(partition by t3.c1) end as bstate
                       from t2,
                            t3
                      where t2.id=t3.c1 and t2.id=t1.id
                   group by t3.c1)
         where bstate>10 );

计划:

从计划上看只能做非相关子查询,即每次获取主查询一条记录去子查询根据条件判断过滤获取结果。为什么会这样?原因是因为exists中select存在主查询条件作为查询项得出结果后还要通过where去过滤,因此只能主查询一条一条去判断,主查询数据量增加,效率急剧下降。这种写法需要转换成相关子查询,即做成相关关联,将子查询做成结果集与主查询关联。

思路拆解

获取子查询结果集,

子查询查询项

sum(sum(t3.ll*0.5)+nvl(max(t2.ll),0)) over(partition by t3.c1)是子查询中获取的

因此可以先把这一部分求出来

c 复制代码
select t3.c1,sum(t3.ll*0.5)+nvl(max(t2.ll),0) as bstate
      from t2, t3 where t2.id=t3.c1 
group by t3.c1

然后与主查询关联条件是t2.id=t1.id,而t2.id=t3.c1那么t3.c1=t1.id

Exists:是判断子查询中是否存在与主查询相匹配的结果。如果相匹配就返回主查询相匹配的结果。它只是判断主查询是否有相匹配的记录,因此exsits只做判断,如果转换成inner join,inner join是获取相匹配的记录,如果子查询结果有重复,与主查询做关联,那会重复输出结果,因此需要子查询去重才能成功转换成inner join。而group by t3.c1(关联列)达到去重效果。

因此可以改写成

c 复制代码
select t1.*,case t1.state when 1 then bstate end bstate
           from t1,
(select t3.c1,sum(t3.ll*0.5)+nvl(max(t2.ll),0) as bstate
      from t2, t3 where t2.id=t3.c1 
group by t3.c1) b where t1.id=b.c1

然后再把查询项获取出来再where处理,最终完成改写。

2、改写

c 复制代码
select count(1)  from (
select t1.*,case t1.state when 1 then bstate end bstate
           from t1,
(select t3.c1,sum(t3.ll*0.5)+nvl(max(t2.ll),0) as bstate
      from t2, t3 where t2.id=t3.c1 
group by t3.c1) b where t1.id=b.c1 ) tt
where bstate>10;

计划:

计划上达到预期的效果,做成关联。

执行时间从

下降至

3、小结

对于这种写法,主要思路是拆解,子查询能获取的先获取,然后找与主查询的关联关系关联主查询,最后做条件过滤。

相关推荐
这个DBA有点耶5 小时前
从MySQL 5.7到8.0:JSON查询性能差在哪?虚拟列索引vs多值索引怎么选
数据库·mysql·架构
胡写代码5 小时前
数据库审计字段,别再每张表各写一套了——我统一成这 6 个字段
数据库
SelectDB9 小时前
为什么 JSON 正在成为分析数据库新的竞争点?
数据库·json·agent
ClouGence10 小时前
开源数据库管理工具 CloudDM 4.2.0 发布,新增 GoldenDB、KingbaseES 等数据源
数据库·dba·devops
发霉的馒头10 小时前
ORA-00845: MEMORY_TARGET not supported on this system的解决方法
数据库
草莓熊Lotso12 小时前
【Redis 初阶】Set 类型深度解析:去重集合的运算能力与实战场景
linux·网络·数据库·windows·redis·tcp/ip·缓存
煎饼皮皮侠13 小时前
【设计】设计一个web版的数据库管理平台后端(之五) --借鉴mybatis
数据库·mybatis
东风破_19 小时前
danci 2:创建的单词书到底存在哪里?从 Supabase 一路理解 ORM、Drizzle 和 RLS
数据库·后端·node.js
九皇叔叔20 小时前
《MySQL 体系架构详解:Server 层、SQL 执行流程与 InnoDB、MyISAM、MEMORY 存储引擎》
sql·mysql·架构
橙子家21 小时前
OSS 文件上传的几个风险点和解决方案
数据库