SQL不计算所选列的总计

时间:2015-07-27 14:07:23

标签: sql tsql sql-server-2005 case window-functions

我需要计算特定范围的产品代码的总价值。我需要进行计算的产品代码是5780,一切都在5700以下。

要获得总价值,我需要这些产品的总成本以及产量。

Value = Pirce * Yield %

为了计算产量,我使用等式:

 CASE 
    WHEN [PC].[ProductCategoryCode] = 5870
            THEN SUM(Sum([PL].[OriginalQuantity_Stk]) / @Credits) OVER (PARTITION BY [PC].[ProductCategoryCode])
    WHEN [PC].[ProductCategoryCode] = 5730
            THEN SUM(Sum([PL].[OriginalQuantity_Stk]) / @Credits) OVER (PARTITION BY [PC].[ProductCategoryCode])
    WHEN [PC].[ProductCategoryCode] = 5990
            THEN SUM(Sum([PL].[OriginalQuantity_Stk]) / @Credits) OVER (PARTITION BY [PC].[ProductCategoryCode])
    ELSE Sum([PL].[OriginalQuantity_Stk]) / @Credits
END

价格已经在系统中,所以我不需要计算。

我已经尝试了几个方程来计算总值,但没有一个能够返回所需的数量。

我觉得它应该类似于这个等式,但这只是显示每行的值而不是一个总值:

SUM(Sum([PL].[OriginalQuantity_Stk]) / @Credits) OVER (
        PARTITION BY (
            CASE 
                WHEN PC.ProductCategoryCode = 5780
                    OR [PC].[ProductCategoryCode] < 5700
                    THEN PC.ProductCategoryCode
                END
            )
        ) * ICP.UnitCost

此等式显示一个总和,但总数不正确:

CASE 
    WHEN [PC].[ProductCategoryCode] = 5780 OR [PC].[ProductCategoryCode] < 5700
        THEN SUM(Sum([PL].[OriginalQuantity_Stk]) / @Credits * [ICP].[UnitCost]) OVER ()
END

我想也许我也需要UnitCost的SUM,但当我尝试在等式中做到这一点时,我会收到错误。

样本表:

Credits        375.00   

Product Code| Weight    | Yield     |Unit Cost| Value           
Pizza       |   150.00  | 40.00%    |   $2.25 | 0.900000    
Potato Chips|   25.00   | 6.60%     |   $1.00 | 0.06600 
Hot Dog     |   125.00  | 33.00%    |   $2.00 | 0.66000 
Soda        |   50.00   | 13.00%    |   $1.50 | 0.195000    
-------------------------------------------------------------
Total       |   350.00  |                     | 1.821000    
Total Value = 1.821000

另一个示例解释了我只想要某些产品代码:

Product Category Code | Value  |
----------------------x--------x
5870                  | 100    |
5730                  | 400    |
5990                  | 200    |
5780                  | 200    |
1111                  | 50     |  
2222                  | 175    |  
3333                  | 500    |  
4444                  | 125    |  
  

总价值:1050       它必须忽略产品代码5870,5990和5730而不包括       那些总价值。

我正在使用Microsoft SQL Sever 2005.如果我需要进一步解释,请告诉我。

完整代码:

SET NOCOUNT ON;

DECLARE @Credits DECIMAL(19, 8);
DECLARE @Price DECIMAL(19, 8);

SET @Credits = 41000;
SET @Price = 1.57;

SELECT CASE 
        WHEN [PC].[ProductCategoryCode] = 5870
            THEN 'Trimmings'
        WHEN [PC].[ProductCategoryCode] = 5730
            THEN 'Rib Tips'
        WHEN [PC].[ProductCategoryCode] = 5990
            THEN 'Skins'
        ELSE [PC].[Description1]
        END AS [Description]
    ,SUM(SUM(PL.OriginalQuantity_Stk)) OVER (
        PARTITION BY (
            CASE 
                WHEN PC.ProductCategoryCode IN (
                        5870
                        ,5730
                        ,5990
                        )
                    THEN PC.ProductCategoryCode
                END
            )
        ) AS [Total Weight]
    ,Sum(CASE 
            WHEN [PC].[ProductCategoryCode] <> 5870
                THEN [PL].[OriginalQuantity_Stk]
            WHEN [PC].[ProductCategoryCode] <> 5730
                THEN [PL].[OriginalQuantity_Stk]
            WHEN [PC].[ProductCategoryCode] <> 5990
                THEN [PL].[OriginalQuantity_Stk]
            END) AS [Weight]
    ,@Credits - SUM(Sum([PL].[OriginalQuantity_Stk])) OVER () AS [Shrink]
    ,CASE 
        WHEN [PC].[ProductCategoryCode] = 5870
            THEN SUM(Sum([PL].[OriginalQuantity_Stk]) / @Credits) OVER (PARTITION BY [PC].[ProductCategoryCode])
        WHEN [PC].[ProductCategoryCode] = 5730
            THEN SUM(Sum([PL].[OriginalQuantity_Stk]) / @Credits) OVER (PARTITION BY [PC].[ProductCategoryCode])
        WHEN [PC].[ProductCategoryCode] = 5990
            THEN SUM(Sum([PL].[OriginalQuantity_Stk]) / @Credits) OVER (PARTITION BY [PC].[ProductCategoryCode])
        ELSE Sum([PL].[OriginalQuantity_Stk]) / @Credits
        END AS [Yield]
    ,CASE 
        WHEN [PC].[ProductCategoryCode] = 5870
            THEN [ICP].[UnitCost]
        WHEN [PC].[ProductCategoryCode] = 5730
            THEN [ICP].[UnitCost] - 0.25
        WHEN [PC].[ProductCategoryCode] = 5990
            THEN [ICP].[UnitCost] * 0
        ELSE [ICP].[UnitCost]
        END AS [UC]
    ,CASE 
        WHEN [PC].[ProductCategoryCode] = 5870
            THEN [ICP].[UnitCost] * SUM(Sum([PL].[OriginalQuantity_Stk]) / @Credits) OVER (PARTITION BY [PC].[ProductCategoryCode])
        WHEN [PC].[ProductCategoryCode] = 5730
            THEN ([ICP].[UnitCost] - 0.25) * SUM(Sum([PL].[OriginalQuantity_Stk]) / @Credits) OVER (PARTITION BY [PC].[ProductCategoryCode])
        WHEN [PC].[ProductCategoryCode] = 5990
            THEN ([ICP].[UnitCost] * 0) * SUM(Sum([PL].[OriginalQuantity_Stk]) / @Credits) OVER (PARTITION BY [PC].[ProductCategoryCode])
        ELSE [ICP].[UnitCost] * SUM(Sum([PL].[OriginalQuantity_Stk]) / @Credits) OVER (PARTITION BY [PC].[ProductCategoryCode])
        END AS [Value]
    ,SUM(Sum([PL].[OriginalQuantity_Stk]) / @Credits) OVER (
        PARTITION BY (
            CASE 
                WHEN PC.ProductCategoryCode = 5780
                    OR [PC].[ProductCategoryCode] < 5700
                    THEN PC.ProductCategoryCode
                END
            )
        ) * ICP.UnitCost AS [TotalValue]
FROM (
    (
        (
            (
                IC_Products [PC] INNER JOIN DC_Transactions [DCT] ON [PC].ProductKey = [DCT].ProductKey
                ) INNER JOIN AR_Customers [ARC] ON [DCT].CustomerKey = [ARC].CustomerKey
            ) INNER JOIN IC_ProductLots [PL] ON [DCT].LotKey = [PL].LotKey
        ) LEFT JOIN IC_ProductCosts [ICP] ON ICP.ProductKey = PC.ProductKey
        AND ICP.ProductCostCode = 5
    )
WHERE (
        [PL].ProductionDate >= { ts '2015-07-10 00:00:00' }
        AND (
            [PL].ProductionDate <= { ts '2015-07-10 00:00:00' }
            OR [PL].ProductionDate IS NULL
            )
        )
    AND (
        (1 = 1)
        AND [ARC].CustomerKey IN (39)
        )
GROUP BY CASE 
        WHEN [PC].[ProductCategoryCode] = 5870
            THEN 'Trimmings'
        WHEN [PC].[ProductCategoryCode] = 5730
            THEN 'Rib Tips'
        WHEN [PC].[ProductCategoryCode] = 5990
            THEN 'Skins'
        ELSE [PC].[Description1]
        END
    ,[ARC].CustomerKey
    ,[PC].ProductCategoryCode
    ,CASE 
        WHEN [PC].[ProductCategoryCode] = 5870
            THEN [ICP].[UnitCost]
        WHEN [PC].[ProductCategoryCode] = 5730
            THEN [ICP].[UnitCost] - 0.25
        WHEN [PC].[ProductCategoryCode] = 5990
            THEN [ICP].[UnitCost] * 0
        ELSE [ICP].[UnitCost]
        END
    ,[ICP].UnitCost
    ,[PC].ProcessCode
ORDER BY @Credits - SUM(Sum([PL].[OriginalQuantity_Stk])) OVER ()
    ,SUM(SUM(PL.OriginalQuantity_Stk)) OVER (
        PARTITION BY (
            CASE 
                WHEN PC.ProductCategoryCode IN (
                        5870
                        ,5730
                        ,5990
                        )
                    THEN PC.ProductCategoryCode
                END
            )
        )

2 个答案:

答案 0 :(得分:1)

好吧,这可能无法按照您想要的方式运作。但是,我试图清理你的代码花了很多时间,但据我所知,你可能甚至不需要窗口版本的SUM函数。 Note: the query below may not properly compile as I do not have exact sample data to test this sample code.

SET NOCOUNT ON;

DECLARE @Credits DECIMAL(19, 8);
DECLARE @Price DECIMAL(19, 8);

SET @Credits = 41000;
SET @Price = 1.57;

BEGIN
SELECT q1.[Description],
       q1.[Total Weight],
       q1.Shrink,
       q1.Yield,
       q1.UC,
       sum(q1.[Value]) AS [Total_Value] 
FROM 
(
--Product codes 5870 and less than 5700
SELECT 
     PC.Description1                                                                            AS [Description]
    ,SUM(PL.OriginalQuantity_Stk)                                                               AS [Total Weight]
    --,Sum(PL.OriginalQuantity_Stk)                                                             AS [Weight]                     
    ,@Credits - Sum(PL.OriginalQuantity_Stk)                                                    AS [Shrink]
    ,(Sum(PL.OriginalQuantity_Stk) / @Credits)                                                  AS [Yield]
    ,ICP.UnitCost                                                                               AS [UC]
    ,ICP.UnitCost * (Sum(PL.OriginalQuantity_Stk) / @Credits)                                   AS [Value]
FROM IC_Products PC 
INNER JOIN DC_Transactions DCT ON PC.ProductKey = DCT.ProductKey
INNER JOIN AR_Customers ARC ON DCT.CustomerKey = ARC.CustomerKey
INNER JOIN IC_ProductLots PL ON DCT.LotKey = PL.LotKey
LEFT JOIN IC_ProductCosts ICP ON ICP.ProductKey = PC.ProductKey
                              AND ICP.ProductCostCode = 5
WHERE ((PL.ProductionDate >= '2015-07-10 00:00:00' AND PL.ProductionDate <= '2015-07-10 00:00:00') OR PL.ProductionDate IS NULL)    
 AND  ARC.CustomerKey = 39
 AND (PC.ProductCategoryCode = 5780 OR PC.ProductCategoryCode < 5700)   --add this check in your where clause to limit to product codes you are interested in

GROUP BY 
     PC.Description1
    ,ARC.CustomerKey
    ,PC.ProductCategoryCode
    ,ICP.UnitCost
    ,PL.ProductionDate

UNION ALL

--Other Product codes 
SELECT 
     PC.Description1                                                                            AS [Description]
    ,SUM(PL.OriginalQuantity_Stk)                                                               AS [Total Weight]
    --,Sum(PL.OriginalQuantity_Stk)                                                             AS [Weight]                   
    ,@Credits - Sum(PL.OriginalQuantity_Stk)                                                    AS [Shrink]
    ,(Sum(PL.OriginalQuantity_Stk) / @Credits)                                                  AS [Yield]
    ,ICP.UnitCost                                                                               AS [UC]
    ,ICP.UnitCost * (Sum(PL.OriginalQuantity_Stk) / @Credits)                                   AS [Value]
    ,(Sum(PL.OriginalQuantity_Stk) / @Credits)* ICP.UnitCost                                    AS [TotalValue]
FROM IC_Products PC 
INNER JOIN DC_Transactions DCT ON PC.ProductKey = DCT.ProductKey
INNER JOIN AR_Customers ARC ON DCT.CustomerKey = ARC.CustomerKey
INNER JOIN IC_ProductLots PL ON DCT.LotKey = PL.LotKey
LEFT JOIN IC_ProductCosts ICP ON ICP.ProductKey = PC.ProductKey
                              AND ICP.ProductCostCode = 5
WHERE ((PL.ProductionDate >= '2015-07-10 00:00:00' AND PL.ProductionDate <= '2015-07-10 00:00:00') OR PL.ProductionDate IS NULL)    
 AND  ARC.CustomerKey = 39
 AND (PC.ProductCategoryCode <> 5780 OR PC.ProductCategoryCode > 5700)   --add this check in your where clause to limit to product codes you are interested in

GROUP BY 
     PC.Description1
    ,ARC.CustomerKey
    ,PC.ProductCategoryCode
    ,ICP.UnitCost
    ,PL.ProductionDate
) AS q1
GROUP BY q1.[Description],
         q1.[Total Weight],
         q1.Shrink,
         q1.Yield,
         q1.UC
END

答案 1 :(得分:0)

也许这就是你所追求的:

SELECT otherColumns, 
       SUM(
        CASE WHEN ProductCategoryCode < 5700 OR ProductCategoryCode=5780 
             THEN OriginalQuantity_Stk 
             ELSE 0 
        END
       ) OVER () / @credits * UnitCost AS tova 
FROM JoinedTables -- WHERE ...

CASE子句需要完全包含在SUM()聚合函数中,然后将结果除以@credits并在之后乘以UnitCost > OVER ()条款。

由于您最初发布的查询有点笨拙,我创建了一个小sqlfiddle只有几列,可以演示我的查询版本基本如何工作(列UnitCost包含我做的任意值向上)。