SQL查找n行的平均值,其中n是字段的总和

时间:2011-06-28 14:58:53

标签: tsql sql-server-2008-r2

我的数据看起来像这样。

SoldToRetailer

OrderDate  | Customer  | Product  | price | units
-------------------------------------------------
1-jun-2011 | customer1 | Product1 | $10   | 5
2-jun-2011 | customer1 | Product1 | $5    | 3
3-jun-2011 | customer1 | Product2 | $10   | 4
4-jun-2011 | customer1 | Product1 | $4    | 4
5-jun-2011 | customer2 | Product3 | $10   | 1

SalesByRetailers

Customer  | Product  | units
-----------------------------
customer1 | Product1 | 5
customer2 | Product3 | 1

这就是我需要的。

销售(平均价格)

Customer  | Product  | units | Average Price
--------------------------------------------
customer1 | Product1 | 5     | $3.44
customer2 | Product3 | 1     | $10

平均价格定义为最近出售的SoldToRetailer价格的平均价格。

所以在第一种情况下,我从6月4日和6月2日获取订单。我不需要(实际上想要)6月1日的订单。

编辑:希望更好的解释。

我正在尝试确定将商品出售给零售商的正确(最近)价格。这是价格的LIFO订单。价格是通过平均过去n个订单的销售价格来确定的。其中n =特定产品和客户的零售总额。

在SQL伪代码中它看起来像这样。

Select s1.Customer, s1.product, average(s2.price)
from SalesByRetailers s1
join SoldToRetailer s2
on s1.customer=s2.customer
and s1.product=s2.product
and ( select top (count of records where s2.units = s1.units) from s2 order by OrderDate desc)

我需要返回的是来自SoldToRetailer的记录数,其中单位总和> = SalesByRetailer Units。

看起来它可以通过RANK或rowover分区解决,但我不知所措。

SoldToRetailer表非常棒,因此性能非常高。

在SQL 2008R2上运行 谢谢你的帮助

2 个答案:

答案 0 :(得分:1)

所以我使用了3种技术。首先,我创建了一个带有over by子句的表,为我提供了产品和价格的排序列表,然后我编辑了表格以添加运行平均值。 OUTER APPLY子选择修复了我的最终问题。希望代码可以帮助其他有类似问题的人。

对于SQLSderverCentral.com的杰夫·莫登(Jeff Moden)大声疾呼,以获得平均运营帮助。

     SELECT d.ProductKey,
         d.ActualDollars,
         d.Units,
         ROW_NUMBER() OVER(PARTITION BY ProductKey ORDER BY d.OrderDateKey DESC) AS RowNumber,
         NULL                                                                  AS RunningTotal,
         CONVERT(DECIMAL(10, 4), 0)                                            AS RunningDollarsSum,
         CONVERT(DECIMAL(10, 4), 0)                                            AS RunningAverage
  INTO   #CustomerOrdersDetails
  FROM   dbo.orders d
  WHERE  customerKey = @CustomerToSelect

  --DB EDIT...  Google "Quirky update SQL Server central.  Jeff Moden's version of a
  --Running total.  Holy crap it's faster.  tried trangular joins before. 
  CREATE CLUSTERED INDEX [Index1]
    ON #CustomerOrdersDetails ( ProductKey ASC, RowNumber ASC )

  DECLARE @RunningTotal INT
  DECLARE @PrevProductKey INT
  DECLARE @RunningDollarsSum DECIMAL(10, 4)

  UPDATE #CustomerOrdersDetails
  SET    @RunningTotal = RunningTotal = CASE
                                          WHEN ProductKey = @PrevProductKey THEN c.Units + ISNULL(@RunningTotal, 0)
                                          ELSE c.Units
                                        END,
         @RunningDollarsSum = RunningDollarsSum = CASE
                                                    WHEN ProductKey = @PrevProductKey THEN c.ActualDollars + ISNULL(@RunningDollarsSum, 0)
                                                    ELSE c.ActualDollars
                                                  END,
         @PrevProductKey = ProductKey,
         RunningAverage = @RunningDollarsSum / NULLIF(@RunningTotal, 0)
  FROM   #CustomerOrdersDetails c WITH (TABLOCKX)
  OPTION (MAXDOP 1)

  -- =============================================
  -- Update Cost fields with average price calculation
  -- =============================================
  UPDATE d
  SET    DolSoldCostUSD = COALESCE(d.DolSoldCostUSD,
                                   d.UnitsSold * a.RunningAverage),
  FROM   dbo.inbound d
         OUTER APPLY (SELECT TOP 1 *
                      FROM   #CustomerOrdersDetails ap
                      WHERE  ap.ProductKey = d.ProductKey
                             AND d.UnitsSold + d.UnitsOnHand + d.UnitsOnOrder + d.UnitsReceived + d.UnitsReturned >= RunningTotal
                      ORDER  BY RunningTotal) AS a

答案 1 :(得分:0)

declare @table table (customer varchar(15), product varchar(15), qty int, price decimal(6,2))

insert into @table (customer, product, qty, price)
values
('customer1', 'product1', 5, 3),
('customer1', 'product1', 4, 4),
('customer1', 'product1', 3, 2),
('customer1', 'product1', 2, 13),
('customer1', 'product1', 3, 3),

('customer1', 'product2', 5, 1),
('customer1', 'product2', 4, 7),
('customer1', 'product2', 2, 5),
('customer1', 'product2', 6, 23),
('customer1', 'product2', 2, 1),

('customer2', 'product1', 2, 1),
('customer2', 'product1', 4, 4),
('customer2', 'product1', 7, 3),
('customer2', 'product1', 1, 12),
('customer2', 'product1', 2, 3),

('customer2', 'product2', 3, 2),
('customer2', 'product2', 6, 5),
('customer2', 'product2', 8, 4),
('customer2', 'product2', 2, 11),
('customer2', 'product2', 1, 2)

select customer, product, sum(qty) as units, (sum(qty * price))/SUM(qty) as 'Average Price' from @table 
group by customer, product