当价格发生变化时查找每个项目的最新生效日期-SQL Server 2014

时间:2018-06-27 11:45:12

标签: sql sql-server sql-server-2012 sql-server-2008-r2 sql-server-2014

我是SQL Server 2014的新用户。我有一个包含以下记录的表。

Year | ItemName | price     | effectivefromdate
===============================================  
2018 | item27   | 1595.0000 | 2017-01-01       
2018 | item27   | 1595.0000 | 2018-03-01       
2018 | item29   | 1000.0000 | 2017-01-01       
2018 | item29   | 1100.0000 | 2018-03-01       
2018 | item30   | 1795.0000 | 2017-01-01       
2018 | item30   | 1795.0000 | 2018-03-01 
2018 | item30   | 1795.0000 | 2018-06-01 
2018 | item32   | 1322.0000 | 2017-01-01       
2018 | item32   | 1350.0000 | 2018-03-01 
2018 | item32   | 1376.0000 | 2018-06-01 

这里每个项目都有一个或多个价格相同或不同的行。当价格发生其他变化时,我必须将每个商品的最新生效日期作为日期 如果没有多个生效日期的价格变化,那么我必须退回具有最小生效日期的商品。

例如,item27有两个条目,但是价格没有变化,因此我必须将价格设为1595,并将生效日期设为2017-01-01 如果是item29,价格已经更改,我必须以1100为价格,生效日期为2018年3月1日。

Expected Output

Year | ItemName | price     | effectivefromdate
===============================================  
2018 | item27   | 1595.0000 | 2017-01-01          
2018 | item29   | 1100.0000 | 2018-03-01       
2018 | item30   | 1795.0000 | 2017-01-01      
2018 | item32   | 1376.0000 | 2018-06-01  

我尝试使用滞后/先导功能,但是没有运气。在过去的两天里,我一直在为此苦苦挣扎。

请为我建议一些解决方案。

3 个答案:

答案 0 :(得分:3)

通过使用Row_Number()

with cte as
(
Select Year, Itemname,price,effectivefromdate, 
ROW_NUMBER() over (Partition by ItemName order by price desc, effectivefromdate asc) as ranking
from tbl 
)
Select  Year, Itemname,price,effectivefromdate from cte where ranking = 1

注意:仅当价格随时间增加时,此功能才起作用。

答案 1 :(得分:2)

您似乎想要最新价格的生效日期。

想法是获取具有最终价格的行集,或者换句话说,在更大的时间戳下没有不同价格的行。

然后合计以获取最早的生效日期:

select year, itemname, price, min(effectivefromdate)
from t
where not exists (select 1
                  from t t2
                  where t2.year = t.year and
                        t2.itemname = t.itemname and
                        t2.effectivefromdate > t.effectivefromdate and
                        t2.price <> t.price
                 )
group by year, itemname, price;

您也可以将其视为“空白与孤岛”问题。但是,这可能会很棘手-特别是如果价格可以在中间的变化之间重复的话。

答案 2 :(得分:2)

您还可以将row_number和group by一起使用,如下所示。查看 working demo here

; with cte as
(
    select *, r= row_number() over( partition by ItemName  order by effectivefromdate desc) from t
   )

 select 
     t1.Year,
     t1.ItemName,
     t1.Price,
     effectivefromdate=min(t2.effectivefromdate) from cte t1 join
    t t2 on r=1 and t1.Year=t2.Year
and t1.ItemName=t2.ItemName and t1.price=t2.price
group by 
    t1.Year,t1.ItemName,t1.Price