我的数据看起来像这样。
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上运行 谢谢你的帮助
答案 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