【问题标题】:How to avoid Internal_Function by TO_CHAR IN Oracle如何通过 TO_CHAR IN Oracle 避免 Internal_Function
【发布时间】:2019-09-16 20:17:41
【问题描述】:

我使用的是 Oracle 12C,我有以下代码:

SELECT *
FROM
    (
    SELECT
        *
    FROM
        t.tablea
    WHERE
        name = 'FIS'
) A
LEFT JOIN (
    SELECT
        *
    FROM
        t.tableb
    WHERE
        enabled = 1
) B ON b.id = a.id
       AND TO_CHAR(b.createdate, 'dd-mm-yy hh24:mi') = TO_CHAR(a.createdate, 'dd-mm-yy hh24:mi')

a 和 b createdate 都是时间戳数据类型。

优化器在执行计划中的 TO_CHAR(b.createdate, 'dd-mm-yy hh24:mi') = TO_CHAR(a.createdate, 'dd-mm-yy hh24:mi') 处返回一个 internal_function

如果我像这样比较:'AND b.createdate = a.createdate',它将丢失 1000 行看起来像这样的 '11-JUN-18 04.48.34.269928000 PM'。如果我将 269928000 更改为 269000000 它将起作用

现在,我不想使用 to_char 来避免 internal_function(必须创建基于函数的索引)

谁能帮帮我?

【问题讨论】:

  • 为什么你会在你的执行计划中看到函数to_char()?您在查询中明确使用它。
  • @a_horse_with_no_name 我并不感到惊讶,我只是想避免它以避免创建基于函数的索引
  • 基于函数的索引有什么问题?
  • @a_horse_with_no_name 我的老板从不同意基于函数的索引,先生

标签: oracle oracle12c to-char


【解决方案1】:

如果我像这样比较:AND b.createdate = a.createdate,它将丢失 1000 行看起来像这样11-JUN-18 04.48.34.269928000 PM。如果我将269928000 更改为269000000 它会起作用

您的值似乎包含小数秒部分,并且具有TIMESTAMP 数据类型。如果是这样,您可以使用TRUNC( timestamp_value, 'MI' ) 截断到最接近的分钟。

SELECT *
FROM   t.tablea a
       LEFT OUTER JOIN t.tableb b
       ON (   a.createdate >= TRUNC( b.createdate, 'MI' )
          AND a.createdate <  TRUNC( b.createdate, 'MI' ) + INTERVAL '1' MINUTE
          AND a.id         =  b.id
          AND b.enabled    =  1
          )
WHERE  a.name = 'FIS'

这将消除对两个表之一应用函数的需要(在这种情况下为a.createdate,但您可以交换它们)。

【讨论】:

    【解决方案2】:

    我什至不认为需要子查询:

    SELECT a.*, b.*
    FROM t.tablea a
    LEFT JOIN t.tableb b
        ON a.id = b.id AND
           TRUNC(b.createdate, 'MI') = TRUNC(a.createdate, 'MI') AND
           b.enabled = 1
    WHERE
        a.name = 'FIS'
    

    【讨论】:

    • 这也会将 2019 年与 1919 年或 2119 年连接起来(如果表中存在此类数据)。我更喜欢TRUNC(b.createdate, 'MI') = TRUNC(a.createdate, 'MI')。在性能方面,它应该与您的方法一样快(或慢)。
    • @Wern 幸好 2119 还没有发生,不是吗?
    • 很可能没有 2119 年的数据,但可能是 1919 年。
    猜你喜欢
    • 2011-05-14
    • 2019-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    • 2023-02-15
    • 2011-11-27
    • 2015-06-14
    相关资源
    最近更新 更多