T-SQL-запрос для получения количества дней, когда товар находился по текущей цене - PullRequest
4 голосов
/ 24 января 2011
Declare @sec_temp table 
(
 sec_no varchar(10),
 amount money,
 price_date date
)

insert @sec_temp
values
    ('123ABC', 25, '2011-01-20'), 
    ('123ABC', 25, '2011-01-19'), 
    ('123ABC', 25, '2011-01-18'), 
    ('123ABC', 20, '2011-01-15'), 
    ('123ABC', 22, '2011-01-13'),
    ('456DEF', 22, '2011-01-13')

Проблема: перечислить отчетливое sec_no с последней ценой (amount) и количество дней, в течение которых оно было по текущей цене. В этом случае

Результат:

sec_no   amount  no_of_days_at_price
123ABC   25      3                   e.g. 01-18 to 01-20
456DEF   22      1                   e.g. 01-13

Ответы [ 2 ]

2 голосов
/ 24 января 2011
select
 a.sec_no,
 a.amount,
 min(price_date) as FirstDateAtPrice,
 No_of_days_at_price = COALESCE(DATEDIFF(d, c.price_date, a.price_date),0)
from (
 select *, ROW_NUMBER() over (partition by sec_no order by price_date desc) rn
 from @sec_temp) a
outer apply (
 select top 1 *
 from @sec_temp b
 where a.sec_no=b.sec_no and a.amount <> b.amount
 order by b.price_date desc
 ) c
where a.rn=1

Подзапрос A определяет наибольшую 1 на группу, то есть самый последний ценовой рекорд для каждого sec_no.Подзапрос C находит первую предыдущую запись, которая содержит другую цену для того же sec_no.Разница в этих двух датах - number of days искомый.Если вам нужно, чтобы это было единица без предшествующей даты, измените конец строки COALESCE на 1 вместо 0.

EDITED для уточненного вопроса

Комуначните отсчет с первой даты, равной текущей ставке, вместо этого используйте этот запрос

select
 sec_no,
 amount,
 No_of_days_at_price = 1 + DATEDIFF(d, min(price_date), max(price_date))
from (
    select *,
  ROW_NUMBER() over (partition by sec_no order by price_date desc) rn,
  ROW_NUMBER() over (partition by sec_no, amount order by price_date desc) rn2
    from @sec_temp
) X
WHERE rn=rn2
group by sec_no, amount

И, наконец, Если требуемый результат фактически равен дням между

  • первая дата, на которую цена равна текущей;и
  • сегодня

Тогда единственное, что нужно изменить, это:

 No_of_days_at_price = 1 + DATEDIFF(d, min(price_date), getdate())
0 голосов
/ 24 января 2011

Вот один из подходов, сначала ищем последнюю цену, а затем последнюю цену, которая была другой:

select  secs.sec_no
,       latest.amount as price
,       case when previous.price_date is null then 1
             else datediff(day, previous.price_date, latest.price_date) 
        end as days_at_price
from    (
        select  distinct sec_no
        from    @sec_temp
        ) secs
cross apply
        (
        select  top 1 amount
        ,       price_date
        from    @sec_temp 
        where   sec_no = secs.sec_no
        order by
                price_date desc
        ) latest
outer apply
        (
        select  top 1 price_date
        from    @sec_temp 
        where   sec_no = secs.sec_no
                and amount <> latest.amount
        order by
                price_date desc
        ) previous

Это печатает:

sec_no  price  days_at_price
123ABC  25,00  5
456DEF  22,00  1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...