【问题标题】:Oracle 11g Nested Case Statement CalculationOracle 11g 嵌套案例语句计算
【发布时间】:2021-11-19 20:52:56
【问题描述】:

在 Oracle 11g 中,我试图从数据查询中获得售价。是的,我可以将其导出并在其他地方编写代码,但我想尝试在查询中优雅地执行此操作。

我似乎只得到等式的第一部分,而不是我使用的最后一个案例:

WHEN sales_code

我最终要做的是从顶部获取结果并将其除以底部,但在 SALE_CODE 4 的情况下,我将 1+1 或 2 添加到顶部结果然后除以等式。

round(to_number(price) *
    CASE    WHEN class_code='X' 
            THEN .48 
            ELSE .5 
    END * e1.set_qty + 
    CASE    WHEN carton_pack_qty = '1' 
            THEN 0 
            ELSE (
                CASE    WHEN NVL(SUBSTR(size, 1,NVL(LENGTH(size) - 2,0)),1) > '35' 
                        THEN 3.5 
                        ELSE 3 
                END) 
    END +
    CASE 
        WHEN sales_code='1' THEN 0 /(1-17/100)
        WHEN sales_code='2' THEN 0 /(1-5/100)
        WHEN sales_code='3' THEN 0 /(1-18/100)
        WHEN sales_code='4' THEN  1+1 / (1-9.5/100)  
        WHEN sales_code='5' THEN  0 /(1-17/100)
        WHEN sales_code='6' THEN  0 /(1-8/100)
        WHEN sales_code='7' THEN 0 /((1-150)/100)
        ELSE (100/100) 
    END,2) AS "Price",

我从查询中得到一个结果,但不是整个计算。我尝试了很多其他方法,但总是出现括号错误或其他任意错误。

任何帮助将不胜感激。

【问题讨论】:

  • 如果您不发布包含错误的minimal reproducible example,我们将无法帮助您
  • 我不明白你在做什么。 0 /(1-17/100)0 /(1-5/100)等当然是零,那你为什么不直接WHEN sales_code In (1,2,3,5,6,7) THEN 0 WHEN sales_code = 4 THEN 1 + (1/0.905) ELSE 1 END呢?
  • 有多个问题: 1) 你不需要为每个条件重复case,因为它只评估第一个满足的分支。所以 case when carton_pack_qty = '1 then 0 when nvl(...) > '35' then 3.5 else 3 end 2) substr 函数返回一个字符串,但它被 nvl(substr, 1) 包裹,它隐式地将数字 (1) 转换为字符串 3) 然后你比较两个数字的字符串表示,这不等同于数字比较'6' 大于'30' 4) 为什么要包括常数计算,其中大部分计算为0?您可以使用常量 0
  • 如果您现在想让您和未来支持者的生活更艰难,切勿使用双引号标识符

标签: sql oracle oracle11g case


【解决方案1】:

我认为这是你的问题:

WHEN sales_code='1' THEN 0 /(1-17/100)

CASE 返回一个标量,一个数字。你试图让它在你的计算中返回公式的后半部分。你需要更多这样的东西:

...
END +
    CASE WHEN sales_code='4' THEN 1 ELSE 0 END /
    CASE 
        WHEN sales_code='1' THEN (1-17/100)
        WHEN sales_code='2' THEN (1-5/100)
        WHEN sales_code='3' THEN (1-18/100)
        WHEN sales_code='4' THEN (1-9.5/100)  
        WHEN sales_code='5' THEN (1-17/100)
        WHEN sales_code='6' THEN (1-8/100)
        WHEN sales_code='7' THEN ((1-150)/100)
        ELSE 1 END ...

实际上,我不完全确定您要使用 sales_code='4' 做什么,但看起来很接近。

【讨论】:

  • 我尝试了这个代码更改,但仍然没有得到预期的结果。 WHERE price is 28.6 和公式将是 (28.6/2+3)/.82) 我得到的结果是 17.3 这是被除数 vs 21.10 这是正确的结果。
  • 您在查询中引用了 5 列,所以我不知道您是如何获得该公式的。一个有数据的例子会有所帮助。
【解决方案2】:

我想我现在明白你想要做什么了。几乎至少:-)

您应该做的第一件事是在需要的地方用括号写下完整的公式。比如:

final = ((price * class_code_factor * set_qty) + quantity_summand + two_if_sales_code4) * sales_code_factor

(最后一部分看起来像是一个百分比因子,对我来说不是除数。我当然可能错了。)

一旦你有正确的公式,将其转换为 SQL:

ROUND
(
  (
    (
      TO_NUMBER(price) *
      CASE WHEN class_code = 'X' THEN 0.48 ELSE 0.5  END *
      e1.set_qty
    )
    + 
    CASE WHEN carton_pack_qty = 1 THEN 0 
         ELSE CASE WHEN NVL(SUBSTR(size, 1,NVL(LENGTH(size) - 2,0)),1) > '35' 
                   THEN 3.5 
                   ELSE 3 
              END 
    END
    +
    CASE WHEN sales_code = 4 THEN 2 ELSE 0 END
  )
  *
  CASE 
    WHEN sales_code = 1 THEN 1 - (17 / 100)
    WHEN sales_code = 2 THEN 1 - (5 / 100)
    WHEN sales_code = 3 THEN 1 - (18 / 100)
    WHEN sales_code = 4 THEN 1 - (9.5 / 100)  
    WHEN sales_code = 5 THEN 1 - (17 / 100)
    WHEN sales_code = 6 THEN 1 - (8 / 100)
    WHEN sales_code = 7 THEN (1 - 150) / 100)
    ELSE 1
  END
, 2 ) AS "Price",

将此调整为您真正想要的公式。有几点我想指出:

  • 为什么价格不是数据库中的数字,而是必须转换为带有TO_NUMBER 的数字的字符串?那一定不是。在数据库中以适当的格式存储值。
  • 在一个好的数据库中,您不必获得size 的子字符串。您似乎在此列中存储了两种不同的东西,这违反了数据库规范化。将这两件事分开并将它们存储在不同的列中。
  • 子字符串看起来也很奇怪。您正在使用size 的左侧部分,而忽略了最后两个字符。因此,您似乎不知道要获得的部分的长度,所以假设这可以是一个、两个或三个字符。 (我当然不知道。)现在你将这个结果与另一个字符串进行比较;一个包含数值的字符串。但是当您比较字符串时,“4”大于“35”,因为“4”>“3”。并且 '200' 小于 '35' 因为 '2'
  • 您将更多内容视为字符串,我冒昧地将其更改为数字。例如,一个数量 (carton_pack_qty) 似乎应该存储为一个数字。所以这样做,不要将它与字符串 '1' 进行比较,而是与数字 1 进行比较。销售代码似乎也是数字。好吧,再说一次,我可能错了。
  • 在一个好的数据库中,查询中不会有幻数。知识属于数据库,而不是查询。如果一个类代码“X”表示因子 0.48,而其他类代码表示因子 0.5,那么为什么没有类代码表显示类代码代表什么以及应用什么因子?神秘的 summand 3 resp 也是如此。 3.5;应该有一个表格,其中包含这些值以及它们适用的大小和数量范围。最后还有销售代码,它也应该存储在一个表格中,显示加法(代码 4 为 2,否则为 0)和因子。

查询部分将如下所示:

ROUND((price * cc.factor * el.set_qty) + qs.value + sc.value) * sc.factor, 2) AS "Price"

【讨论】:

    【解决方案3】:

    将被除数分解为子查询有效,然后在其周围添加括号以在主查询中除以。

        (
        select 
        style,
        to_number(price) *
        CASE    WHEN class_code='X' 
                THEN .48 
                ELSE .5 
        END * set_qty + 
        CASE    WHEN carton_pack_qty = '1' 
                THEN 1 
                ELSE (
                    CASE    WHEN to_number(NVL(SUBSTR(size, 1,NVL(LENGTH(size) - 2,0)),1)) > 35 
                            THEN 3.5 
                            ELSE 3 
                    END) 
        END as Price
        FROM STYL1 s1,STY2 s2
        WHERE s1.style=s2.style
    ) P1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-30
      • 1970-01-01
      相关资源
      最近更新 更多