【问题标题】:Mathematical operation between two columns in a comparison比较中两列之间的数学运算
【发布时间】:2014-09-02 04:32:22
【问题描述】:

我们使用的是 Oracle 10g XE,我们发现以下查询没有返回任何值:

SELECT ref.referencia,
       ref.descripcio,
       stock_reservat,
       stock,
       stock_p_rebre,
       (SELECT count(*)
          FROM ref_numeros_serie num
          WHERE num.empresa=ref.empresa AND
                num.referencia=ref.referencia AND
                num.diposit=1 AND
                nvl(num.actiu,'N')='S') cnt_nums_serie
  FROM emp_referencies ref,
       ref_stk_dip_acu stk
  WHERE ref.empresa=1 AND
        ref.referencia='1B' AND
        stk.empresa=ref.empresa AND
        stk.referencia=ref.referencia AND
        stk.diposit=1 AND
        -- Relevant part
        (stk.stock - stk.stock_reservat) <> (SELECT count(*)
                                             FROM ref_numeros_serie num
                                             WHERE num.empresa=ref.empresa AND 
                                                   num.referencia=ref.referencia AND 
                                                   num.diposit=1 AND 
                                                   nvl(num.actiu,'N')='S') 
        -- End of relevant part
  GROUP BY ref.empresa,
           ref.referencia,
           ref.descripcio,
           stk.stock,
           stk.stock_reservat,
           stock,
           stock_p_rebre

所以减法和子查询之间的比较是假的。但是如果我们像这样交换子查询和减法:

SELECT ref.referencia,ref.descripcio,
       stock_reservat,
       stock, 
       stock_p_rebre,
       (SELECT count(*)
          FROM ref_numeros_serie num
          WHERE num.empresa=ref.empresa AND
                num.referencia=ref.referencia AND
                num.diposit=1 AND
                nvl(num.actiu,'N')='S') cnt_nums_serie
  FROM emp_referencies ref,
       ref_stk_dip_acu stk
  WHERE ref.empresa=1 AND
        ref.referencia='1B' AND
        stk.empresa=ref.empresa AND
        stk.referencia=ref.referencia AND
        stk.diposit=1 AND
        -- Relevant part
        (SELECT count(*)
           FROM ref_numeros_serie num
           WHERE num.empresa=ref.empresa AND
                 num.referencia=ref.referencia AND
                 num.diposit=1 AND
                 nvl(num.actiu,'N')='S') <> (stk.stock - stk.stock_reservat)
        -- End of relevant part
  GROUP BY ref.empresa,
           ref.referencia,
           ref.descripcio,
           stk.stock,
           stk.stock_reservat,
           stock,
           stock_p_rebre 

比较是真的,我们得到结果。

我们尝试过以下案例:

  • 删除减法的第二部分,所以比较的左边部分是stk.stock:我们得到结果,正确
  • 将减法的第二部分更改为这样的数字stk.stock-2:我们得到结果,正确
  • 交换比较的左右部分,如上所述:我们得到结果,正确
  • 像这样更改算术运算符(stk.stock+stk.stock_reservat) &lt;&gt; subquery:没有结果,不正确
  • 用这样的数字更改子查询(stk.stock-stk.stock_reservat) &lt;&gt; 2:我们得到结果,正确

我们已经用 10g 非 XE 数据库尝试了这些情况,它具有相同的行为。另一方面,使用 11g 时,它工作得非常好。

所以我们的结论是,在 oracle 10g 中,仅当子查询位于左侧而操作位于右侧时,两列之间的算术运算与子查询之间的比较才有效。有没有人遇到过类似的问题,您是如何解决/修复它的?

编辑:我想补充一点,当子查询结果为 0 时会发生这种情况,否则我们没有遇到问题,即它的行为符合预期。

【问题讨论】:

  • 尝试将(stk.stock - stk.stock_reservat) 更改为(stk.stock - NVL(stk.stock_reservat, 0)) 看看是否有帮助。分享和享受。
  • 我们已经尝试过了,但没有成功
  • 您的所有补丁都是最新的吗?我记得 10g 有问题,正如您所注意到的,11 稳定得多。

标签: oracle oracle10g


【解决方案1】:

您的查询可以通过使用子查询分解子句来简化,如下所示:

WITH ns AS (SELECT r.empresa, r.referencia, count(*) as CNT_NUMS_SERIE
              FROM ref_numeros_serie n
              INNER JOIN emp_referencies r
                r.empresa = n.empresa AMD
                r.referencia = n.referencia 
              WHERE n.diposit = 1 AND
                    NVL(n.actiu, 'N') = 'S'
              GROUP BY r.empresa,
                       r.referencia)
SELECT ref.referencia,
       ref.descripcio,
       stock_reservat,
       stock,
       stock_p_rebre,
       ns.CNT_NUMS_SERIE
  FROM emp_referencies ref
  INNER JOIN ref_stk_dip_acu stk
    ON stk.empresa = ref.empresa AND
       stk.referencia = ref.referencia
  INNER JOIN ns
    ON ns.empresa = ref.empresa AND
       ns.referencia = ref.referencia
  WHERE ref.empresa = 1 AND
        ref.referencia = '1B' AND
        stk.diposit = 1 AND
        -- Relevant part
        (stk.stock - NVL(stk.stock_reservat, 0)) <> ns.CNT_NUMS_SERIE
        -- End of relevant part
  GROUP BY ref.empresa,
           ref.referencia,
           ref.descripcio,
           stk.stock,
           stk.stock_reservat,
           stock,
           stock_p_rebre

这使您可以将常用表达式 (SELECT COUNT(*)...) 拉出并将其视为单独的表。我认为它使查询更易于阅读,并且可能会节省一些执行时间。

分享和享受。

【讨论】:

    猜你喜欢
    • 2016-03-15
    • 2023-03-27
    • 2022-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多