如何从结果为null的左连接返回一种子纹理的“0”销售额

时间:2013-11-24 11:47:37

标签: sql derby

DBMS:Derby

语言:Java

外部查询从内部查询中获取结果 它在某个日期内获得了某种子纹理的销售 但有时候某种类型的订单细节没有 subtexture。所以没什么可加入的,我想看一个“0” 对于这种情况。抱歉,错误的命名和缩进。 谢谢 千斤顶

SELECT s1.TextureName AS TYPE,
       T.month AS MONTH,
       NULLIF(sum(S.Sales),0) AS NS,
       NULLIF(T.Total,0) AS total,
       NULLIF(NULLIF(cast(S.Sales AS Float),0.0) / NULLIF(Cast(T.Total AS float),0.0) * 100.0,0.0) AS percent
FROM subtexture s1
LEFT JOIN
  (SELECT s.SubTextureID,
          sum(od.NetSales) AS Sales,
          MONTH(o.PURCHASEDATETIME) AS MONTH
   FROM subtexture s
   LEFT JOIN products p ON (s.SubTextureID = p.SubTextureID)
   LEFT JOIN order_details od ON (p.ProductCode = od.ProductCode)
   LEFT JOIN orders o ON (od.OrderCode = o.OrderCode)
   WHERE TRIM(CAST(CAST(YEAR(o.PurchaseDateTime) AS CHAR(4)) AS VARCHAR(4))) || '-' || TRIM(CAST(CAST(MONTH(o.PurchaseDateTime) AS CHAR(2)) AS VARCHAR(2))) = '2013-11'
   GROUP BY s.SubTextureID,
            MONTH(o.PurchaseDateTime)) AS S ON (S.SubTextureID = s1.SubTextureID) ,
  (SELECT sum(od.NetSales) AS Total,
          MONTH(o.PurchaseDateTime) AS MONTH
   FROM orders o
   LEFT JOIN order_details od ON (o.OrderCode = od.OrderCode)
   WHERE TRIM(CAST(CAST(YEAR(o.PurchaseDateTime) AS CHAR(4)) AS VARCHAR(4))) || '-' ||TRIM(CAST(CAST(MONTH(o.PurchaseDateTime) AS CHAR(2)) AS VARCHAR(2))) = '2013-11'
   GROUP BY MONTH(o.PURCHASEDATETIME)) AS T
WHERE T.MONTH = S.MONTH
GROUP BY s1.TextureName,
         T.Total,
         T.MONTH,
         S.Sales

2 个答案:

答案 0 :(得分:0)

NULLIF(sum(S.Sales),0) AS NS,
...
NULLIF(NULLIF(cast(S.Sales AS Float),0.0) / NULLIF(Cast(T.Total AS float),0.0) * 100.0,0.0) AS percent

这永远无法奏效。稍微简化一下,你这样做:

SELECT sum(S.Sales),
       S.Sales

您如何设想将销售总额和个人销售同时归入同一个退货记录?由于您按销售分组,因此SUM(Sales)在任何时候都等于Sales,这让我相信您可能正在尝试完成查询中未反映的内容。

答案 1 :(得分:0)

我认为代码存在一些问题。不幸的是我没有表格和测试数据。所以请记住,我的结果或多或少都是出于我的想法。仔细测试。

为了便于阅读,我将代码分为两个步骤。第一步获得销售总额,第二步计算所有纹理的总销售额并构建百分比。对于您的测试,将第一个代码复制两次到第二个代码中,替换SALES_ONE_TEXTURE的两个出现。我只是不想在必要时淹没答案。

以下是一个纹理(以及月份和年份)的销售总额的第一部分

-- Use this as subselect. And you're right: you need it twice
(   select  s.TextureName, s.SubTextureId, o.year, o.month, sum(COALESCE(d.NetSales, 0)) NetSales
    from    (select SubTextureId, TextureName from subtexture) as s
    join
            (select SubTextureId, ProductCode from products) as p
        on  (p.SubTextureId = s.SubTextureId)
    left outer join
            (select ProductCode, OrderCode, NetSales from order_details) as d
        on  (d.ProductCode = p.ProductCode)
    join
            (   select  YEAR(o.PurchaseDateTime) year,
                        MONTH(o.PurchaseDateTime) month,
                        OrderCode
                from    orders
                where   o.PurchaseDateTime between '2013-11-01 00:00:00' and '2013-11-30 23:59:59' -- make use of an index if one exists
            ) as o
        on  (o.orderCode = d.orderCode)
    group by 1,2,3,4
)   as SALES_ONE_TEXTURE;

这里是将数字组合在一起的外部代码:

-- The outer query
select  O.TextureName,
        A.year, A.month,
        A.NetSales, O.NetSales,
        cast(O.NetSales as float) / cast(A.NetSales as float) * 100.0 as percent
from    SALES_ONE_TEXTURE O -- replace here
join
        (   select  year, month, sum(NetSales) as NetSales
            from    SALES_ONE_TEXTURE -- replace here
            group by 1, 2 
        ) as SALES_ALL_TEXTURES A
    on  (A.year = O.year and A.month = O.month)

说明

  • COALESCE返回第一个非空值,通常用于将空值替换为默认值。 NULLIF执行相反的操作:将值替换为null。
  • 替换来自外部联接的null不适用于所有RDBMS上的所有方言。你必须尝试,如果它在这里工作。如果没有,您需要将整个查询放在子选择中并在外部选择中执行coalesce替换
  • 我过了一年又一个月,你过了一个月。每个月都会重复一个月,所以只有这种组合才是独一无二的。我也改变了获得月份的方式。我的方式可以使用索引(如果存在)。