Ваш вопрос не ясен ... Вы добавили пример данных, но я сомневаюсь, что это правильно ...
Ваша таблица цен открыта для ошибочных данных. Лучше хранить только цену и дату validFrom
. В этом случае вы можете легко выбрать цену на конкретную дату. Ваш формат открыт для перекрывающихся периодов, и нет веских оснований для сохранения прежней цены еще раз. Вот почему я игнорирую все поля, которые вы не должны использовать ...
Попробуй это. Я изменил даты таким образом, чтобы имитировать периодичность действия.
Сценарий
A макет (пожалуйста, в следующий раз для нас):
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
Я бы добавил встроенную табличную функцию , чтобы получить ровно одну строку назад.
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
-подход. Идея та же.