在Oracle中的SELECT语句中,如何基于另一个表中存在的值高效地添加列/变量?

nhaq1z21  于 2023-02-07  发布在  Oracle
关注(0)|答案(2)|浏览(204)

我有两个表文件和错误:

还有

我想创建一个结果集,其中包含虚拟编码变量,如下所示:

我可以让它在CASE语句和EXISTS语句中工作,如下所示:

SELECT f.detail_id, 
(CASE WHEN EXISTS 
    (SELECT * FROM errors e WHERE f.detail_id = e.detail_id AND e.error_code = 400) 
    THEN 1 ELSE 0 END) AS error_400, 
(CASE WHEN EXISTS 
    (SELECT * FROM errors e WHERE f.detail_id = e.detail_id AND e.error_code = 405) 
    THEN 1 ELSE 0 END) AS error_405, 
(CASE WHEN EXISTS 
    (SELECT * FROM errors e WHERE f.detail_id = e.detail_id AND e.error_code = 410) 
    THEN 1 ELSE 0 END) AS error_410, 
(CASE WHEN EXISTS 
    (SELECT * FROM errors e WHERE f.detail_id = e.detail_id AND e.error_code = 392) 
    THEN 1 ELSE 0 END) AS error_392, 
(CASE WHEN EXISTS 
    (SELECT * FROM errors e WHERE f.detail_id = e.detail_id AND e.error_code = 401) 
    THEN 1 ELSE 0 END) AS error_401 
FROM files f

然而,这段代码效率很低,运行速度慢,而且运行时间长。我怎样才能重写这段代码使它更有效率?我怎样才能优化它?
先谢谢你的帮助。

yqkkidmi

yqkkidmi1#

由于您没有选择文件号或名称,因此通过聚合错误表可以获得几乎相同的结果:

select
  detail_id,
  count(case when error_code = 400 then 1 end) as error_400,
  count(case when error_code = 405 then 1 end) as error_405,
  count(case when error_code = 410 then 1 end) as error_410,
  count(case when error_code = 392 then 1 end) as error_392,
  count(case when error_code = 401 then 1 end) as error_401
from errors
group by detail_id
order by detail_id;

在聚合函数中使用布尔表达式称为条件聚合。
上面的查询没有返回detail_id,虽然它出现在文件中,但不会出现在错误中。如果需要,可以将上面的结果外部连接到文件表。

vmjh9lq9

vmjh9lq92#

而且,我认为你应该有一个索引:

create index error_det_id_i on errors(detail_id);

这在任何情况下都可以提高性能。

select
  detail_id, 
  sum(case
    when error_code=400 then 1
    else 0
  end) cnt_err_400,
  sum(case
    when error_code=400 then 1
    else 0
  end) cnt_err_405,
  sum(case
    when error_code=400 then 1
    else 0
  end) cnt_err_410
from files f
left join errors e on f.detail_id=e.detail_id
group by detail_id;

相关问题