Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TSQL从物料价格更改中获取物料价格历史记录_Tsql_Sql Server 2016 - Fatal编程技术网

TSQL从物料价格更改中获取物料价格历史记录

TSQL从物料价格更改中获取物料价格历史记录,tsql,sql-server-2016,Tsql,Sql Server 2016,我有一个物品价格变化表,我想用它来创建物品发布日期和结束日期之间每个日期的物品价格表 以下是一些创建日期的代码:- declare @Item table (item_id int, item_launch_date date, item_end_date date); insert into @Item Values (1,'2001-01-01','2016-01-01'), (2,'2001-01-01','2016-01-01') declare @ItemPriceChanges

我有一个物品价格变化表,我想用它来创建物品发布日期和结束日期之间每个日期的物品价格表

以下是一些创建日期的代码:-

declare @Item table (item_id int, item_launch_date date, item_end_date date); 

insert into @Item Values (1,'2001-01-01','2016-01-01'), (2,'2001-01-01','2016-01-01')

declare @ItemPriceChanges table (item_id int, item_price money, my_date date); 

INSERT INTO @ItemPriceChanges VALUES (1, 123.45, '2001-01-01'), (1, 345.34, '2001-01-03'), (2, 34.34, '2001-01-01'), (2,23.56 , '2005-01-01'), (2, 56.45, '2016-05-01'), (2, 45.45, '2017-05-01'); ;
我想看到的是这样的东西:-

item_id  date       price
-------  ----       -----
1        2001-01-01 123.45
1        2001-01-02 123.45
1        2001-01-03 345.34
1        2001-01-04 345.34
etc.
2        2001-01-01  34.34
2        2001-01-02  34.34
etc.
关于如何编写查询有什么建议吗? 我正在使用SQL Server 2016

增加: 我还有一个叫做dim_calendar的日历表,每天一行。我曾希望使用窗口功能,但最近我能找到的是铅,它没有做我认为它会做的:-

select 
    i.item_id,
    c.day_date,
    ipc.item_price as item_price_change,
    lead(item_price,1,NULL) over (partition by i.item_id ORDER BY c.day_date) as item_price
from dim_calendar c
inner join @Item i
on c.day_date between i.item_launch_date and i.item_end_date
left join @ItemPriceChanges ipc
on i.item_id=ipc.item_id
and ipc.my_date=c.day_date
order by 
    i.item_id,
    c.day_date;

谢谢

在您编辑之前,我写了这篇文章。请注意,您的示例输出表明,一个项目在价格更改当天可以有两个价格。以下假设一个项目在价格变动日只能有一个价格,即新价格

declare @Item table (item_id int, item_launch_date date, item_end_date date); 

insert into @Item Values (1,'2001-01-01','2016-01-01'), (2,'2001-01-01','2016-01-01')

declare @ItemPriceChange table (item_id int, item_price money, my_date date); 

INSERT INTO @ItemPriceChange VALUES (1, 123.45, '2001-01-01'), (1, 345.34, '2001-01-03'), (2, 34.34, '2001-01-01'), (2,23.56 , '2005-01-01'), (2, 56.45, '2016-05-01'), (2, 45.45, '2017-05-01'); 

SELECT * FROM @ItemPriceChange

-- We need a table variable holding all possible date points for the output

DECLARE @DatePointList table (DatePoint date);

DECLARE @StartDatePoint date = '01-Jan-2001';

DECLARE @MaxDatePoint date = GETDATE();

DECLARE @DatePoint date = @StartDatePoint;

WHILE @DatePoint <= @MaxDatePoint BEGIN

    INSERT INTO @DatePointList (DatePoint)
        SELECT @DatePoint;

    SET @DatePoint = DATEADD(DAY,1,@DatePoint);

END;

-- We can use a CTE to sequence the price changes

WITH ItemPriceChange AS (
    SELECT item_id, item_price, my_date, ROW_NUMBER () OVER (PARTITION BY Item_id ORDER BY my_date ASC) AS SeqNo
    FROM @ItemPriceChange
)

-- With the price changes sequenced, we can derive from and to dates for each price and use a join to the table of date points to produce the output. Also, use an inner join back to @item to only return rows for dates that are within the start/end date of the item

SELECT ItemPriceDate.item_id, DatePointList.DatePoint, ItemPriceDate.item_price
FROM @DatePointList AS DatePointList
INNER JOIN (
    SELECT ItemPriceChange.item_id, ItemPriceChange.item_price, ItemPriceChange.my_date AS from_date, ISNULL(ItemPriceChange_Next.my_date,@MaxDatePoint) AS to_date
    FROM ItemPriceChange
    LEFT OUTER JOIN ItemPriceChange AS ItemPriceChange_Next ON ItemPriceChange_Next.item_id = ItemPriceChange.item_id AND ItemPriceChange.SeqNo = ItemPriceChange_Next.SeqNo - 1
) AS ItemPriceDate ON DatePointList.DatePoint >= ItemPriceDate.from_date AND  DatePointList.DatePoint < ItemPriceDate.to_date
INNER JOIN @item AS item ON item.item_id = ItemPriceDate.item_id AND DatePointList.DatePoint BETWEEN item.item_launch_date AND item.item_end_date
ORDER BY ItemPriceDate.item_id, DatePointList.DatePoint;

@阿尔法斯塔一号完美!我将其修改为使用窗口功能而不是自连接,但您的建议有效。下面是我的实现,以防其他人需要它:

SELECT 
    ipd.item_id, 
    dc.day_date, 
    ipd.item_price
FROM dim_calendar dc
INNER JOIN (
    SELECT 
        item_id, 
        item_price, 
        my_date AS from_date,
        isnull(lead(my_date,1,NULL) over (partition by item_id ORDER BY my_date),getdate()) as to_date
    FROM @ItemPriceChange ipc1
) AS ipd 
ON dc.day_date >= ipd.from_date 
AND dc.day_date < ipd.to_date
INNER JOIN @item AS i 
ON i.item_id = ipd.item_id 
AND dc.day_date BETWEEN i.item_launch_date AND i.item_end_date
ORDER BY 
    ipd.item_id, 
    dc.day_date;

你能分享没有产生你想要的结果的代码吗?Stackoverflow似乎不允许在评论中出现符号,所以我编辑了我的原始帖子,以显示我的代码不起作用。很抱歉,这是我的示例输出中的一个错误。每天每件商品一个价格是我想要的。我已经更正了这个问题。那么我相信这正是您所需要的-您可以取出StartDatePoint和DatePointList,并用日历表替换SELECT中对它的引用。保留MaxDatePoint,除非您想调整CTE以使用项目结束日期。