【问题标题】:ORACLE SQL: Need to sum two values, but one may not exist... Is this possible?ORACLE SQL:需要对两个值求和,但一个可能不存在......这可能吗?
【发布时间】:2010-09-22 21:16:45
【问题描述】:

在将一些旧的 ASP 文件复制到一些较新的 .NET 2.0 代码中时,我遇到了一些问题。其中一项任务是将 4-5 条 SQL 语句合并为一条。虽然我已经做到了这一点并在性能提升方面取得了一些成功,但 Oracle 对我来说是一个新包。然而,这个问题超出了我自己的 SQL 技能,因为我以前没有这样做过。

基本上,我在一堆销售中的一张表中有一个 QUANTITY。每个销售都有一个整数值。每个销售还附有一个项目。每个项目都有一个转换因子,就像我卖 1 袋东西 = 10 捆东西一样。因此,当我运行报告并想找出最终价值时,我需要将每笔销售及其数量乘以它的转换因子。大多数都是简单的1对1,所以基本上就是25 * 1、30 * 1等。

我的问题是我的记录中有过去的销售项目已从我们的系统中删除,因此不存在转换因素。这些记录从我的查询中删除,因为 FACTOR 已经消失了。

SELECT rth.CODE, rth.NUMBER, rth.QUANTITY, rth.sale_code 
FROM salesdetails rth, salesheader rsh
WHERE rsh.number = rth.number(+)
AND rsh.customer_code = '05'
AND rsh.r_code = '01'
AND rsh.location_code = '12'
AND rth.sale_code IN('ITEM07')
AND rth.c_code = 'WLMT'
AND rsh.year = '2008'

这是我的第一个查询。如果我将转换添加到:

SELECT rth.CODE, rth.NUMBER, rth.QUANTITY, rth.sale_code, rth.quantity * cf.conversion
FROM salesdetails rth, salesheader rsh, conversionfactor cf
WHERE rsh.number = rth.number(+)
AND rsh.customer_code = '05'
AND rsh.r_code = '01'
AND rsh.location_code = '12'
AND rth.sale_code IN('ITEM07')
AND rth.c_code = 'WLMT'
AND rsh.year = '2008'
AND cf.item_code = rth.item_code
and cf.code = '01'
and cf.loc_code = '00001'

这在一定程度上有效。它列出了所有相同的记录,但它缺少任何不存在 CONVERSION 因素的记录。无论如何,我仍然可以在第二个查询中包含那些 FACTOR 不存在的记录,而不是逐行进行转换。

【问题讨论】:

    标签: sql oracle plsql oracle10g


    【解决方案1】:

    如果您处理空值和数字,请考虑使用“coalesce”函数,将列表中的第一个非空值作为结果传回。

    【讨论】:

      【解决方案2】:

      现在我无法访问 Oracle。看看这个查询:

      SELECT rth.CODE, rth.NUMBER, rth.QUANTITY, rth.sale_code, rth.quantity * cf.conversion
      FROM salesdetails rth, salesheader rsh, conversionfactor cf
      WHERE rsh.number = rth.number(+)
      AND rsh.customer_code = '05'
      AND rsh.r_code = '01'
      AND rsh.location_code = '12'
      AND rth.sale_code IN('ITEM07')
      AND rth.c_code = 'WLMT'
      AND rsh.year = '2008'
      AND rth.item_code  =  cf.item_code (+)
      and cf.code = '01'
      and cf.loc_code = '00001'
      

      【讨论】:

        【解决方案3】:

        我想你正在丢失记录,因为你试图乘以一个空值。看看将 NVL() 与您的转换因子一起使用,以将其默认为 1 或其他适合您的默认值。

        喜欢,

        SELECT rth.CODE, rth.NUMBER, rth.QUANTITY, rth.sale_code, rth.quantity * NVL(cf.conversion,1)
        FROM salesdetails rth, salesheader rsh, conversionfactor cf
        WHERE rsh.number = rth.number(+)
        AND rsh.customer_code = '05'
        AND rsh.r_code = '01'
        AND rsh.location_code = '12'
        AND rth.sale_code IN('ITEM07')
        AND rth.c_code = 'WLMT'
        AND rsh.year = '2008'
        AND cf.item_code = rth.item_code
        and cf.code = '01'
        and cf.loc_code = '00001'
        

        请仔细检查 NVL 语法。自从我与 Oracle 合作以来已经有几年了。

        【讨论】:

          【解决方案4】:

          实际上,关于 OUTER JOIN,您是对的。我当时认为它所做的事情存在技术问题,但我明白为什么它仍然没有包含价值。其他两个条件必须是 (+) 才能包含 NULL。我将它与 COALESCE 结合起来,它似乎起作用了。

          【讨论】:

            【解决方案5】:

            您还可以使用 Coalesce 函数,带有子查询...

            依次评估每个参数并返回它找到的第一个不是 Null 的参数。 >

            Select D.CODE, D.NUMBER, D.QUANTITY, D.sale_code, 
                D.quantity * Coalesce((Select conversion 
                                       From conversionfactor
                                       Where item_code = H.item_code
                                          And code = '01'
                                          And loc_code = '00001'), 1.0)
            From salesheader H
               Left Join salesdetails D
                 On D.Number = H.Number
            Where H.customer_code = '05'
               And H.r_code = '01'
               And H.location_code = '12'
               And H.year = '2008'
               And D.sale_code In ('ITEM07')
               And D.c_code = 'WLMT'
            

            将子查询末尾的 1.0 替换为您希望当记录不再在转换因子表中时转换因子的“默认”值...

            【讨论】:

              【解决方案6】:

              outer 从 rsh 连接到 rth 但然后 inner 从 rth 连接到 cf 是没有意义的。使它们都成为外部连接。此外,(+) 符号必须出现在 rth 的所有连接条件的“外侧”:

              SELECT rth.CODE, rth.NUMBER, rth.QUANTITY, rth.sale_code,
                     rth.quantity * cf.conversion
              FROM salesdetails rth, salesheader rsh, conversionfactor cf
              WHERE rsh.number = rth.number(+)
              AND rsh.customer_code = '05'
              AND rsh.r_code = '01'
              AND rsh.location_code = '12'
              AND rth.sale_code (+) IN('ITEM07')
              AND rth.c_code (+) = 'WLMT'
              AND rsh.year = '2008'
              AND cf.item_code (+) = rth.item_code
              and cf.code (+) = '01'
              and cf.loc_code (+) = '00001'
              

              顺便说一句,这是非常老式的语法。为什么不使用更现代的:

              SELECT rth.CODE, rth.NUMBER, rth.QUANTITY, rth.sale_code,
                     rth.quantity * cf.conversion
              FROM salesheader rsh
              LEFT OUTER JOIN salesdetails rth
                 ON  rsh.number = rth.number
                 AND rth.sale_code IN ('ITEM07')
                 AND rth.c_code = 'WLMT'
              LEFT OUTER JOIN conversionfactor cf
                 ON  cf.item_code = rth.item_code
                 AND cf.code = '01'
                 AND cf.loc_code = '00001'
              WHERE rsh.customer_code = '05'
              AND rsh.r_code = '01'
              AND rsh.location_code = '12'
              AND rsh.year = '2008'
              

              【讨论】:

              • 我同意使用最现代的语法。
              • 是的,现代的;自 1992 年以来! :-)
              • 因为更现代的语法更加冗长且难以阅读。世界语比英语更现代,但我没有看到大量皈依者。
              • 我同意更冗长,但更难阅读?旧式外连接语法的一个问题是(如这里的问题)缺少一个 (+) 会破坏连接的“外部”性质,并且很容易被忽略。
              【解决方案7】:

              我相信 SQL 假定我有一个空记录。我没有,当转换不存在时,我根本没有记录。如果我能找到一种方法来为我的数据库中不存在的那些 CONVERSION 返回 null,我可以这样做。

              【讨论】:

              • 其实没有。如果你对表进行了左外连接,并且对应的记录不存在,如果你尝试引用它,它将返回null
              • 顺便说一句。您可以将 cmets 添加到答案中(50+ 声望),因为它将它们保留在上下文中
              • 他现在可能有 50 多个...但不是在他添加评论时
              【解决方案8】:

              我认为这应该可行。假设转换因子不存在时等于1

              select 
                  rth.code, rth.number, rth.quantity, rth.sale_code, rth.quantity * coalesce(cf.conversion,1)
              from 
                  salesdetails rth
                  inner join  salesheader rsh on rsh.number = rth.number
                  left join conversionfactor cf on cf.item_code = rth.item_code
              where 
              rsh.customer_code = '05'
              and rsh.r_code = '01'
              and rsh.location_code = '12'
              and rth.sale_code in('item07')
              and rth.c_code = 'wlmt'
              and rsh.year = '2008'
              and cf.code = '01'
              and cf.loc_code = '00001'
              

              【讨论】:

              • 来自jrolin的评论:“我相信SQL假设我有一个空记录。我没有,当转换不存在时我根本没有记录。如果我能找到方法返回对于那些在我的数据库中不存在的 CONVERSION,我可以做到这一点。”
              • 其实没有。你测试了吗? LEFT JOIN 的工作方式是,如果你对表进行了左外连接,并且相应的记录不存在,如果你尝试引用它,它将返回 null
              【解决方案9】:

              不,我相信 OUTER JOIN 不起作用,因为记录实际上并不存在。它不为空,只是不存在了。

              【讨论】:

              • 这正是外连接的作用。使用外连接,您将能够从其他表中检索所有数据,并为转换值检索空值。这样,将 Dheer 查询中的 cf.conversion 替换为 nvl(cf.conversion, 1)。因此,当没有值时,它将使用 1。
              猜你喜欢
              • 2012-01-15
              • 2011-04-07
              • 2011-05-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多