Использование функции LAG () для поиска прошлого значения - PullRequest
1 голос
/ 14 марта 2020

Я использовал функцию запаздывания, чтобы найти предыдущее значение. Однако я столкнулся с проблемой, которая требует более сложного запроса.

Вот мой сценарий. Наша таблица в настоящее время хранит данные на конец месяца для каждой записи. За исключением последних 95 дней. нам нравится вести ежедневные записи за последние 95 дней. Вот что я имею в виду под окончанием месяца и ежедневными записями

ID      Date       Amount 
123  10/31/2019      52
123  11/31/2019      56
123  12/31/2019      59
123  01/25/2020      32
123  01/26/2020      28  
123      ...         ..   
123  03/12/2020      103

Представьте себе, что ... представляют ежедневную запись для id: 123 до вчерашнего дня.

Моя задача отлично сработала для нашего исторические данные на конец месяца, но я столкнулся с проблемой с нашими ежедневными историческими данными

, и я хочу получить последнее значение за последний день предыдущего месяца для всех месяцев.

это то, что у меня сейчас есть для моего запроса

Select ID, Date, Amount,LAG(Amount, 1, 0) OVER(PARTITION BY ID
   ORDER BY id,
            Date)
   AS SharePreviousBalance from dbo.shares
where date >= 20191031

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

ID      Date       Amount  SharePreviousBalance
123  10/31/2019      52         0
123  11/31/2019      56         52
123  12/31/2019      59         56
123   ...            ..         ..
123  01/25/2020      32         0
123  01/26/2020      28         0
123  01/27/2020      28         0
123      ...         ..         ..
123  01/31/2020      28         59
123     ...          ..         ..
123  02/15/2020      28         0
123      ...         ..         ..
123  02/29/2020      25         28
123      ...         ..         ..
123  03/05/2020      29         0
123      ...         ..         ..
123  03/10/2020      30         0
123      ...         ..         ..
123  03/12/2020      103        25

Есть идеи?

Спасибо

1 Ответ

3 голосов
/ 14 марта 2020

С небольшим условным логикой c вы все равно можете сделать это с помощью lag():

select
    t.*,
    case when date = eomonth(date) then 
        coalesce(
            lag(amount) over(
                partition by id, case when date = eomonth(date) then 1 else 0 end
                order by date
            ),
            0
        )
    end SharePreviousBalance
from mytable t

Идея состоит в том, чтобы создать раздел для строк на конец месяца (ie строки, у которых date - последний день месяца). В этом разделе строка на конец месяца может получить доступ к предыдущему концу месяца с lag().

Демонстрация на DB Fiddle - я добавил несколько строк в данных образца:

 ID | Date       | Amount | SharePreviousBalance
--: | :--------- | -----: | -------------------:
123 | 2019-10-31 |     52 |                    0
123 | 2019-11-30 |     56 |                   52
123 | 2019-12-31 |     59 |                   56
123 | 2020-01-20 |     28 |                 <em>null</em>
123 | 2020-01-25 |     32 |                 <em>null</em>
123 | 2020-01-26 |     28 |                 <em>null</em>
123 | 2020-01-31 |     28 |                   59
123 | 2020-02-12 |    103 |                 <em>null</em>
123 | 2020-02-28 |    103 |                 <em>null</em>
123 | 2020-02-29 |    103 |                   28

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

select
    t.*,
    case when date in (eomonth(date), cast(getdate() as date)) then 
        coalesce(
            lag(amount) over(
                partition by 
                    id, 
                    case when date in (eomonth(date), cast(getdate() as date)) then 1 else 0 end
                order by date
            ),
            0
        )
    end SharePreviousBalance
from mytable t
order by id, date
...