替换Union All以加入以提高性能

时间:2018-04-03 08:08:30

标签: sql oracle performance union-all

我有一个工作查询,需要20分钟才能返回数据。我想优化它。 我有桌子

激励:

Transaction_ID | Incentive_On_A  | Incentive_On_B  | Incentive_On_C
--------------+-----------------+-----------------+---------------
1             | 0               | 0               | 10
2             | 30              | 0               | 0
3             | 0               | 20              | 0
4             | 40              | 0               | 0

必需输出:

Transaction_ID| Product_Category | Incentive_Amt
 ----------   + -----------------+--------------
  1           | A                | 30
  2           | B                | 20
  3           | C                | 10
  4           | A                | 40

我正在使用此查询:

   select Transaction_ID, 'A' as Product_Category,
       Incentive_On_A from Incentives
Union all
   select Transaction_ID, 'B' as Product_Category,
       Incentive_On_B from Incentives
Union all
   select Transaction_ID, 'C' as Product_Category,
       Incentive_On_C from Incentives

有什么办法可以通过删除union all来优化这个查询吗? 非常感谢您的帮助。

编辑** 1.在两个表中再添加一行。 注意: - 基本上我们只是进行数据转置 - 将列''Incentive_on_A','Incentive_on_B','Incentive_on_C'转换为列 - 'Category',具有上述3列的值。

2 个答案:

答案 0 :(得分:0)

首先:这是一个糟糕的数据模型。如果每条记录只能有一个值,那么只需存储一个值,完全如所需的输出所示。

按原样,您只需添加所有值并使用CASE WHEN查看哪个值大于零:

select
  transaction_id,
  case when incentive_on_a > 0 then 'A'
       when incentive_on_b > 0 then 'B'
       when incentive_on_c > 0 then 'C'
  end as product_category,
  incentive_on_a + incentive_on_b + incentive_on_c as incentive_amt
from incentives
order by transaction_id;

(但是,我仍然没有看到像你所展示的这样简单的查询如何运行二十分钟。)

答案 1 :(得分:0)

您在这里不需要JOIN,只需要取消数据:

SELECT transaction_id, REGEXP_SUBSTR(incentive_col, '[^_]*$') AS product_category
     , incentive_amt
  FROM (
    SELECT transaction_id, incentive_a, incentive_b, incentive_c
      FROM incentives
) UNPIVOT (
    incentive_amt 
      FOR incentive_col IN (incentive_a, incentive_b, incentive_c )
) WHERE incentive_amt > 0;

这是否会真正改善你的表现,我不能说。我的猜测是,对于查询的UNION ALL版本,您实际上是在进行3次全表扫描。