1

我有一个很大的查询(不是我写的,但我正在做一些修改)。让我烦恼的一件事是,我在大约四个地方都有相同的 COALESCE 功能。有没有办法解决这个问题,可能是通过从 DUAL 中选择加入?将其分解出来是否有性能优势?

这是稍微粗略的查询:

select 
tbl1.gid
[snip]
         ,COALESCE(t1_end_dt, t6_actl_end_dt,t6_calc_end_dt) perd_end_dt
        ,t1_end_dt
FROM    tbl1
....
JOIN    tbl2               ON (t2_pk          = wpck_wrkr_id  AND
                                            t2_ind_1    ='Y'    AND
        COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt) 
        BETWEEN  t2_strt_dt AND t2_end_dt)
JOIN    tbl3                ON (t3_pk               = t2_fk_t3_pk AND
       COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt) 
        BETWEEN t3_strt_dt AND t3_end_dt)    
LEFT JOIN tbl4 tbl4_a             ON (tbl4_a.t4_pk         = chkw_wkt_id)
.....
GROUP BY tbl1.gid 
.....
        ,COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt)
        ,COALESCE(tbl4_b.t4_or_id, tbl4_a.t4_or_id, t7_or_id )
        ,t1_end_dt
ORDER BY perd_end_dt

请注意,我已经通过在 SELECT 中将其命名为 pred_end_dt 并然后在 ORDER BY 中通过该名称引用它来分解出其中一个 COALESCE。

4

4 回答 4

2

您应该能够用您的列别名替换 GROUP BY 子句中的出现perd_end_dt。但是 JOIN 条件中的出现不能使用列别名。

这确实对性能有影响。我不认为 JOIN 条件可以按照它们当前的编写方式使用索引。但是,它只是 JOIN 条件中的一项,因此影响可能很小。也就是说,涉及的术语t2_pk可能t2_ind_1已经减少了行集,因此日期比较只需要处理一个小集合。这取决于我们谈论的行数以及数据的分布方式。

一种分解COALESCE()并利用索引的方法是创建一个冗余列,它是该表达式的结果。使用触发器确保在每次插入或更新后它具有正确的值。然后索引列。

但就像我说的,这可能比它的价值更麻烦。这将是更多的工作,并且您应该确保此更改将使代码更易于维护、更正确或更快。


另一种选择是为COALESCE()子查询中的表达式定义别名。我不知道这些列来自哪些表,因为您没有使用表别名来限定它们。但是,如果我可以假设它们都是以tbl1下列:

...
FROM (
    SELECT COALESCE(t1_end_dt, t6_actl_end_dt, t6_calc_end_dt) perd_end_dt,
      t1_fk_t2_pk
    FROM tbl1) t1
  JOIN tbl2
    ON (tbl2.t2_pk = t1.t1_fk_t2_pk AND tbl2.t2_ind_1 = 'Y'
      AND t1.perd_end_dt BETWEEN tbl2.t2_strt_dt AND tbl2.t2_end_dt)
...
于 2009-01-16T18:36:48.157 回答
1

也许你可以使用 with 子句?

with data as
(
   select COALESCE(t1_end_dt, t6_actl_end_dt,t6_calc_end_dt) perd_end_dt
   ,      .....
   ,      ...
   from   tbl1
)
select ...
from   data
,      ....
where  ....
于 2009-01-16T18:33:45.167 回答
1

你可以创建一个虚拟表

(Select Coalesce( all your stuff ....) perdEndDt 
   From [all your tables necessary for this one value])

并将此作为单独的联接表包含在您的 Select SQL 中

  Select [all yr other stuff,
      Z.perdEndDt
  From [Other Tables Joined together]
      Join 
         (Select Coalesce( all your stuff ....) perdEndDt,
               [other columns necessary for join conditions]
         From [all your tables necessary for this one value]) As Z
         On [Join conditions for Z to other tables]
  Where  [any filter predicates]
  Order By Z.perdEndDt
     ... etc.  
于 2009-01-16T18:38:56.170 回答
1

甲骨文有意见吗?(必须这样做。)如果您发现自己COALESCE()在许多不同的地方使用该表达式,则可能值得创建一个VIEW并使用它而不是原始表。下面将执行相同的计算,但查询的语法会更简洁,因此更清晰。

在我看来,“视图”是数据库中的“表”,就像“函数”是程序中的“代码行”一样。每当您发现一堆使用相似逻辑的查询时,请编写一个将通用逻辑分解的视图并改用它。

于 2009-01-16T19:38:45.567 回答