【Oracle SQL】把某表列值借助码值表由代号转换成名称的SQL,子查询效率未必低
有一张emp722表结构和数据如下:
create table emp722( id number(10), f1 nvarchar2(20), f2 nvarchar2(20), f3 nvarchar2(20), f4 nvarchar2(20), primary key(id) ); insert into emp722(id,f1,f2,f3,f4) values(1,'1','2','3','4'); insert into emp722(id,f1,f2,f3,f4) values(2,'4','3','2','1');
还有一张辅助的表dic722结构及数据如下:
create table dic722( code nvarchar2(20), name nvarchar2(20), primary key(code) ); insert into dic722(code,name) values('1','A'); insert into dic722(code,name) values('2','B'); insert into dic722(code,name) values('3','C'); insert into dic722(code,name) values('4','D');
【需求】
将emp722中1,2,3,4通过dic722表置换成A,B,C,D的形式。
【子查询解决方案】
SQL:
select e.id, (select name from dic722 where code=e.f1) as f1, (select name from dic722 where code=e.f2) as f2, (select name from dic722 where code=e.f3) as f3, (select name from dic722 where code=e.f4) as f4 from emp722 e
运行:
luna@ORCL>select 2 e.id, 3 (select name from dic722 where code=e.f1) as f1, 4 (select name from dic722 where code=e.f2) as f2, 5 (select name from dic722 where code=e.f3) as f3, 6 (select name from dic722 where code=e.f4) as f4 7 from emp722 e; ID F1 F2 F3 F4 ---------- ---------- ---------- ---------- ---------- 1 A B C D 2 D C B A 已选择2行。
解释计划:
PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Plan hash value: 2973185055 -------------------------------------------------------------------------------- ------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU) | Time | -------------------------------------------------------------------------------- ------------ PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 2 | 202 | 3 (0) | 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| DIC722 | 1 | 44 | 1 (0) | 00:00:01 | |* 2 | INDEX UNIQUE SCAN | SYS_C0011561 | 1 | | 1 (0) | 00:00:01 | | 3 | TABLE ACCESS BY INDEX ROWID| DIC722 | 1 | 44 | 1 (0) | 00:00:01 | PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- |* 4 | INDEX UNIQUE SCAN | SYS_C0011561 | 1 | | 1 (0) | 00:00:01 | | 5 | TABLE ACCESS BY INDEX ROWID| DIC722 | 1 | 44 | 1 (0) | 00:00:01 | |* 6 | INDEX UNIQUE SCAN | SYS_C0011561 | 1 | | 1 (0) | 00:00:01 | | 7 | TABLE ACCESS BY INDEX ROWID| DIC722 | 1 | 44 | 1 (0) PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- | 00:00:01 | |* 8 | INDEX UNIQUE SCAN | SYS_C0011561 | 1 | | 1 (0) | 00:00:01 | | 9 | TABLE ACCESS FULL | EMP722 | 2 | 202 | 3 (0) | 00:00:01 | -------------------------------------------------------------------------------- ------------ PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("CODE"=:B1) 4 - access("CODE"=:B1) 6 - access("CODE"=:B1) 8 - access("CODE"=:B1) Note ----- PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- - dynamic sampling used for this statement (level=2) 已选择28行。
可以看到其cost是3.
【表连接查询解决方案】
SQL:
select a.id, listagg(a.f1,',') within group (order by id) as f1, listagg(a.f2,',') within group (order by id) as f2, listagg(a.f3,',') within group (order by id) as f3, listagg(a.f4,',') within group (order by id) as f4 from ( select e.id, decode(e.f1,d.code,d.name,'') as f1, decode(e.f2,d.code,d.name,'') as f2, decode(e.f3,d.code,d.name,'') as f3, decode(e.f4,d.code,d.name,'') as f4 from emp722 e,dic722 d ) a group by a.id
执行:
luna@ORCL>select 2 a.id, 3 listagg(a.f1,',') within group (order by id) as f1, 4 listagg(a.f2,',') within group (order by id) as f2, 5 listagg(a.f3,',') within group (order by id) as f3, 6 listagg(a.f4,',') within group (order by id) as f4 7 from 8 ( 9 select 10 e.id, 11 decode(e.f1,d.code,d.name,'') as f1, 12 decode(e.f2,d.code,d.name,'') as f2, 13 decode(e.f3,d.code,d.name,'') as f3, 14 decode(e.f4,d.code,d.name,'') as f4 15 from emp722 e,dic722 d 16 ) a 17 group by a.id; ID F1 F2 F3 F4 ---------- ---------- ---------- ---------- ---------- 1 A B C D 2 D C B A 已选择2行。
解释计划:
-------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 8 | 1160 | 8 (13)| 00:00:01 | | 1 | SORT GROUP BY | | 8 | 1160 | 8 (13)| 00:00:01 | | 2 | MERGE JOIN CARTESIAN| | 8 | 1160 | 7 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL | EMP722 | 2 | 202 | 3 (0)| 00:00:01 | | 4 | BUFFER SORT | | 4 | 176 | 5 (20)| 00:00:01 | | 5 | TABLE ACCESS FULL | DIC722 | 4 | 176 | 2 (0)| 00:00:01 | PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- Note ----- - dynamic sampling used for this statement (level=2) 已选择16行。
Cost为8,不如上面的3,说明这种方案效率还不如子查询方案。
END
分类:
Oracle.权衡比较Sql文
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
2017-07-22 【Canvas与标志】黄黑辐射警示标志