Как ускорить SQL при поиске по предыдущей дате? - PullRequest
1 голос
/ 30 апреля 2019

Таблица t1 имеет 200 тыс. Записей, и первые несколько записей:

 -----------------------------
 |    date   |  id    | value |
 -----------------------------
 | 2/28/2019 |  abc1    | 55  |
 | 2/28/2019 |  abc2    | 44  |
 | 2/28/2019 |  abc3    | 33  |
 | 2/26/2019 |  abc1    | 22  |
 | 2/26/2019 |  abc2    | 12  |
 | 2/25/2019 |  abc1    | 11  |
 | 2/25/2019 |  abc3    | 10  |
 | 2/24/2019 |  abc1    | 10  |
 | 2/24/2019 |  abc2    | 10  |
 -----------------------------

Я хочу взять abc1 из t1, а затем найти значение abc1 для предыдущей даты (это может быть -1 день или -2 дня или -3 дня ... но это будет точно за последние 5 дней) и отобразить разница (значение первой даты - значение предыдущей даты).

Я создал запрос, который отлично работает для этого (но медленно):

select 
    a.date, a.id, a.value, b.value, a.value-b.value
from 
    t1 a
inner join 
    t1 b
on 
    a.id = b.id
where 
    b.date = (
        select 
            max(date) from t1
            where 
                date < a.date
                and date > dateadd(day, -5, a.date)
    )

Это прекрасно работает, но очень медленно для записей 200K (занимает минуты).

Как ускорить это? (возможно, используя RANK или другой более эффективный подход ..)

Ожидаемый результат:

2/28/2019 | abc1 | 33     (which is "55 - 22")
2/28/2019 | abc2 | 32     (which is "44 - 12")
2/28/2019 | abc3 | 23     (which is "33 - 10")

Спасибо!

1 Ответ

2 голосов
/ 30 апреля 2019

Использование lag():

select t1.*,
       value - lag(value) over (partition by id order by date)
from t1;

В любой используемой вами базе данных должна быть возможность использовать индекс для (id, date, value).

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

select t1.*,
       (case when date < dateadd(day, 5, lag(date) over (partition by id order by date))
             then value - lag(value) over (partition by id order by date)
        end)
from t1;
...