代码之家  ›  专栏  ›  技术社区  ›  Paul Tomblin

分解出合并函数?

  •  1
  • Paul Tomblin  · 技术社区  · 15 年前

    我有一个很大的问题(不是我写的,但我正在做一些修改)。有一件事让我很头疼,那就是我在四个地方都有相同的合并函数。有没有一种方法可以将这一点考虑在内,可能的话,加入一个从双重选择中选择的方案?将它分解出来是否有性能上的好处?

    下面是稍微Bolwderized的查询:

    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中用该名称引用它来分解一个合并。

    4 回复  |  直到 15 年前
        1
  •  2
  •   Paul Tomblin    15 年前

    您应该能够用列别名替换group by子句中的出现项。 perd_end_dt . 但联接条件中的出现不能使用列别名。

    这确实会影响性能。我不认为加入 条件可以按照当前写入的方式使用索引。然而, 它只是连接条件中的一个术语,因此影响可能非常大 轻微的也就是说,涉及 t2_pk t2_ind_1 可能已经减少了行集,因此日期比较只需要处理一个小的集合。这取决于我们谈论的行数以及数据的分布方式。

    其中一个因素是 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)
    ...
    
        2
  •  1
  •   Charles Bretana    15 年前

    你可以用板条箱装一张虚拟桌子

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

    并将此ASA单独的联接表包含在所选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.  
    
        3
  •  1
  •   j_random_hacker    15 年前

    Oracle有视图吗?如果你发现自己在使用它 COALESCE() 在许多不同的地方表达,可能值得创造一个 VIEW 并使用它而不是原始表。在下面,将执行相同的计算,但查询的语法将更简洁,因此更清晰。

    在我看来,“视图”是将数据库中的“表”作为“函数”来表示程序中的“代码行”。每当您发现一组使用类似逻辑的查询时,请编写一个视图,将通用逻辑考虑在内,并使用它。

        4
  •  1
  •   Paul Tomblin    15 年前

    也许你可以用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  ....