限制价格变动表以选择特定商品
select * from price
where item = '13'
上面查询的结果
item Date_Changed New Old START_DATE end_DATE
13 01/11/2018 00:00 5.61 4.88 01/11/2018 00:00 30/11/2018 00:00
13 30/11/2018 00:00 2.84 5.61 01/11/2018 00:00 17/12/2018 00:00
13 17/12/2018 00:00 2.39 2.84 30/11/2018 00:00 17/12/2018 00:00
销售表
Date Item Qty Amount
05/07/2018 00:00 13 3 14.64
05/07/2018 00:00 13 3 14.64
04/07/2018 00:00 13 3 14.64
02/07/2018 00:00 13 1 4.88
02/07/2018 00:00 13 6 29.28
06/07/2018 00:00 13 7 34.16
03/07/2018 00:00 13 4 19.52
12/07/2018 00:00 13 2 9.76
10/08/2018 00:00 13 1 4.88
示例代码
SELECT distinct a.[Inv]
, (CASE
WHEN a.Date <= b.START_DATE THEN (b.Old * a.Qty)
WHEN a.Date between b.START_DATE and b.dt_end_DATE THEN (b.New * a.Qty)
ELSE 0
END) as calc_amount
,(a.[amount] - (CASE
WHEN a.Date <= b.START_DATE THEN (b.Old * a.Qty)
WHEN a.Date between b.START_DATE and b.end_DATE THEN (b.New * a.Qty)
ELSE 0
END)) as variance
[sales] a
left outer join price b
on a.[Item] = b.item
where b.item = '13'
然后,脚本返回27行而不是9行。有人可以协助我改善我的脚本以使其更准确吗
答案 0 :(得分:1)
使用outer apply
。我假设您想要的是price
的最新开始日期,所以看起来像这样:
select s.*,
(case when s.date <= p.start_date
then p.Old * s.Qty
else p.New * s.Qty
end) as calc_amount
from sales s outer apply
(select top (1) p.*
from prices p
where p.item = s.item and
p.start_date <= s.date
order by p.date desc
) p
答案 1 :(得分:0)
我不确定这是否是您想要的。但是也许您可以跳过加入?
我用可能需要的列创建了2个样本数据。
DECLARE @price table (item varchar(2),date_start date, new_price numeric(9,2))
Insert into @price (item , date_start,new_price)
values
( '13', '20190101', '1.00'),
( '13', '20190102', '1.01'),
( '13', '20190103', '1.02')
DECLARE @sales table (item varchar(2),date_sales date,qty int)
Insert into @sales (item , date_sales,qty)
values
( '13', '20190101', '5'),
( '13', '20190101', '2'),
( '13', '20190102', '5'),
( '13', '20190102', '2'),
( '13', '20190103', '5'),
( '13', '20190103', '2')
declare @item as varchar(2) = '13'
SELECT (select top (1) new_price from @price b where a.date_sales>=b.date_start and b.item = @item order by b.date_start desc ) * a.qty as 'new_price* qty'
from @sales a
where a.item = @item
我尚未在具有庞大数据集的表中对此进行测试,因此我也无法保证此查询的速度。我相信最好有某种其他ID来加入表格
答案 2 :(得分:0)
您的问题尚不清楚...您添加了示例数据,但我怀疑这是正确的...
您的价格表对错误数据开放。最好只存储价格和validFrom
日期。在这种情况下,您可以轻松地给定日期选择价格。您的格式容易出现重叠的时期,因此没有充分的理由再次存储以前的价格。这就是为什么我忽略所有不应使用的字段的原因...
尝试一下。我已经更改了日期以模拟有效期。
一个模拟场景(请下次再试):
CREATE TABLE priceMock(item INT, Date_Changed DATE, New DECIMAL(10,4), Old DECIMAL(10,4), [START_DATE] DATE, end_DATE DATE);
SET DATEFORMAT dmy;
INSERT INTO priceMock VALUES
(13,'01/11/2018 00:00',5.61,4.88,'01/07/2018 00:00','06/07/2018 00:00')
,(13,'30/11/2018 00:00',2.84,5.61,'07/07/2018 00:00','10/07/2018 00:00')
,(13,'17/12/2018 00:00',2.39,2.84,'11/07/2018 00:00','15/08/2018 00:00');
GO
CREATE TABLE salesMock ([Date] DATE, Item INT, Qty INT, Amount DECIMAL(10,4));
SET DATEFORMAT dmy;
INSERT INTO salesMock VALUES
('05/07/2018 00:00',13,3,14.64)
,('05/07/2018 00:00',13,3,14.64)
,('04/07/2018 00:00',13,3,14.64)
,('02/07/2018 00:00',13,1,4.88 )
,('02/07/2018 00:00',13,6,29.28)
,('06/07/2018 00:00',13,7,34.16)
,('03/07/2018 00:00',13,4,19.52)
,('10/07/2018 00:00',13,2,9.76 )
,('10/08/2018 00:00',13,1,4.88 );
GO
我将添加一个 inline-table-valued-function 来获得一条单行。
CREATE FUNCTION dbo.GetPriceForItemOnDate(@item INT,@ValidOn DATE)
RETURNS TABLE
AS
RETURN
SELECT TOP 1 *
FROM priceMock
WHERE item=@item
AND [START_DATE] <= @ValidOn
ORDER BY [START_DATE] DESC
GO
-此查询将结合您的销售数据和给定日期的有效价格
SELECT s.[Date]
,s.Item
,s.Qty
,p.New AS CurrentPrice
,s.Qty * p.New AS ComputedAmount
FROM salesMock s
OUTER APPLY dbo.GetPriceForItemOnDate(s.item,s.[Date]) p
GO
-清理(仔细处理真实数据)
DROP FUNCTION dbo.GetPriceForItemOnDate;
DROP TABLE priceMock;
DROP TABLE salesMock;
简而言之:
该功能将首先过滤给定项目的价格线。第二个过滤器将剪切列表,并仅返回给定日期和给定日期之前的价格。当我们按日期降序排序时,我们将获得最新的价格。通过使用TOP 1
,我们只返回我们想要的一行。
一般性说明:我在这里使用validFrom
方法。但是您可以反过来使用validTo
方法。想法是一样的。