简体   繁体   中英

Find latest effective date for each item when there is a price change - SQL Server 2014

I am new the SQL Server 2014. I have a table with records like the below.

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 

Here each item have one or more lines with same or different prices. I have to take the latest effective date for each item when the price has changed other wise If there is no price change with multiple effective dates then I have to return the item with minimum effective date.

For example, item27 have two entries but the price is not changed so I have to take price as 1595 and effective date as 2017-01-01 In case of item29, the price has changed here I have to take 1100 as price and effective date as 2018-03-01.

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  

I tried with Lag/Lead function but no luck. I am struggling for the past two days with this.

Please suggest me some solution to solve this.

By using 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

Note: This works only when price increases with time.

You seem to want the effective date of the most recent price.

The idea is to get the set of rows that have the final price -- or said differently, that do not have a different price with a larger timestamp.

Then aggregate to get the earliest effective date:

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;

You can also approach this as a gaps-and-islands problem. However, this can be tricky -- particularly if prices can repeat with changes in-between.

You can also using row_number and with group by like below. See a 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM