Найти последнюю дату вступления в силу для каждого товара при изменении цены - SQL Server 2014 - PullRequest
0 голосов
/ 27 июня 2018

Я новичок в 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 

Здесь каждый элемент имеет одну или несколько строк с одинаковыми или разными ценами. Я должен взять самую последнюю дату вступления в силу для каждого элемента, когда цена изменилась Если с несколькими датами вступления в силу цены не изменяются, я должен вернуть товар с минимальной датой вступления в силу.

Например, в позиции 27 есть две записи, но цена не изменилась, поэтому я должен принять цену за 1595, а дату вступления в силу за 2017-01-01 В случае пункта 29 здесь изменилась цена, поэтому в качестве цены и даты вступления в силу необходимо указать 1100. 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  

Я пытался использовать функцию Lag / Lead, но безуспешно. Последние два дня я борюсь с этим.

Пожалуйста, предложите мне какое-нибудь решение, чтобы решить эту проблему.

Ответы [ 3 ]

0 голосов
/ 27 июня 2018

Вы также можете использовать row_number и group, как показано ниже. Смотрите рабочую демонстрацию здесь

; 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
0 голосов
/ 27 июня 2018

Используя 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

Примечание: работает только тогда, когда цена увеличивается со временем.

0 голосов
/ 27 июня 2018

Похоже, вы хотите дату вступления в силу самой последней цены.

Идея состоит в том, чтобы получить набор строк, которые имеют окончательную цену или, иначе говоря, не имеют другой цены с большей отметкой времени.

Затем агрегируйте, чтобы получить самую раннюю дату вступления в силу:

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;

Вы также можете подходить к этому как к проблеме пробелов и островков. Однако это может быть сложно - особенно если цены могут повториться с изменениями между ними.

...