Как я могу использовать функцию LAG в сочетании с предложением WHERE?

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

Это означает, что LAG следует применять к полю previous_availability следующим образом:

значение_дата будущее_доступность предыдущая_доступность точная_дата Текущий EOD 10 НУЛЕВОЙ 2020-12-18 возмещение 2 10 2020-12-19 возмещение 3 10 20.12.2020 возмещение 4 10 2020-12-22 возмещение 5 10 2022-01-18 использование 6 10 2022-01-19 возмещение 7 6 2022-03-18 Ограничить срок погашения 8 6 2022-07-18 возмещение 9 8 2025-01-01

Спасибо!

Есть ли такой столбец, как id, который определяет порядок строк?

forpas 25.12.2020 11:54

"...до последнего с безвозмездным типом". Непонятно, как найти этот последний, потому что нет позиции, по которой заказаны эти данные (или эти данные не приведены в заданном вопросе).

Luuk 25.12.2020 11:55

Почему «возмещение», которое следует за «использованием», имеет значение 10? Я бы ожидал 6 (предыдущий ряд не возмещение).

GMB 25.12.2020 12:01

@forpas, столбца ID нет, но есть столбец даты, и все записи упорядочены по дате

Houssem Timoumi 25.12.2020 12:03

@GMB, ты совершенно прав!!! я починил это

Houssem Timoumi 25.12.2020 12:05

@Luuk, есть дата, и они упорядочены по дате, я добавил это сейчас!

Houssem Timoumi 25.12.2020 12:06

@HoussemTimoumi: Тогда вы можете использовать мой ответ в качестве основы для своего решения 😉. Удачи в изменении применения его к вашей ситуации!

Luuk 25.12.2020 12:08
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
7
390
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

(ПРИМЕЧАНИЕ: это было опубликовано ДО того, как к вопросу был добавлен precise_date )

Если у вас есть индекс на id:

-- drop table mytable;
create table mytable (
  id integer,
  value_date varchar(20),
  future_availability integer);

insert into mytable values
(1,'Current EOD',             10),
(2,'reimbursment',            2 ),
(3,'reimbursment',            3 ),                       
(4,'reimbursment',            4 ),
(5,'reimbursment',            5 ),
(6,'utilization',             6 ),
(7,'reimbursment',            7 ),
(8,'Limit Maturity',          8 ),
(9,'reimbursment',            9 );


select 
   value_date, 
   future_availability,
   (select TOP 1 m2.future_availability 
    from mytable m2 
    where m2.id<m1.id and m2.value_date<>'reimbursment' 
    order by id desc
    ) as previous_availability
from mytable m1;

вывод будет:

+ --------------- + ------------------------ + -------------------------- +
| value_date      | future_availability      | previous_availability      |
+ --------------- + ------------------------ + -------------------------- +
| Current EOD     | 10                       |                            |
| reimbursment    | 2                        | 10                         |
| reimbursment    | 3                        | 10                         |
| reimbursment    | 4                        | 10                         |
| reimbursment    | 5                        | 10                         |
| utilization     | 6                        | 10                         |
| reimbursment    | 7                        | 6                          |
| Limit Maturity  | 8                        | 6                          |
| reimbursment    | 9                        | 8                          |
+ --------------- + ------------------------ + -------------------------- +

Но он не использует функцию LAG.

Обновлено: удалено limit 1 и добавлено TOP 1, потому что речь идет о MSSQL.

Я исправил запрос следующим образом: --(выберите TOP 1 t8.future_availability -- из #temp8 t8 -- где t8.precise_value_date<t8.precise_value_date и t8.value_date NOT LIKE '%reimbursment%' -- упорядочить по точному_value_date ASC -- ) AS 'previous_availability' Однако это не работает, все значения предыдущих и будущих возможностей обнуляются, а LIMIT в любом случае недоступен для использования в SQL Server 18.

Houssem Timoumi 25.12.2020 12:18

Хорошо, я писал решение для MySQL, а не для MSSQL, моя вина.... 😥

Luuk 25.12.2020 12:24

все нормально!!! Вы исправите ответ, пожалуйста?

Houssem Timoumi 25.12.2020 12:26

@HoussemTimoumi: я изменил ответ, чтобы использовать синтаксис MSSQL, а не синтаксис MySQL.

Luuk 25.12.2020 12:28

@HoussemTimoumi: в своем комментарии выше измените ASC на DESC.

Luuk 25.12.2020 12:31

Во-первых: чтобы вопрос имел смысл, вам нужен столбец, определяющий порядок строк — я предположил id.

Тогда, я думаю, вы хотите что-то вроде этого:

select id, value_date, future_availability,
    lag(future_availability, rn) over(order by id) as previous_availability
from (
    select t.*,
        row_number() over(partition by grp order by id) as rn
    from (
        select t.*,
            sum(case when value_date = 'reimbursment' then 0 else 1 end) 
                over(order by id rows between unbounded preceding and 1 preceding) as grp
        from mytable t
    ) t
) t

Это рассматривает вопрос как проблему пробелов и островов. Идея состоит в том, чтобы использовать оконную сумму для идентификации группы смежных записей; затем мы можем ранжировать записи и использовать эту информацию для передачи правильного смещения в lag().

Демо на DB Fiddle:

id | value_date     | future_availability | previous_availability
-: | :------------- | ------------------: | --------------------:
 1 | Current EOD    |                  10 |                  null
 2 | reimbursment   |                   2 |                    10
 3 | reimbursment   |                   3 |                    10
 4 | reimbursment   |                   4 |                    10
 5 | reimbursment   |                   5 |                    10
 6 | utilization    |                   6 |                    10
 7 | reimbursment   |                   7 |                     6
 8 | Limit Maturity |                   8 |                     6
 9 | reimbursment   |                   9 |                     8

Мой MySQL8.0 дает ERROR 1327 (42000): Undeclared variable: rn (но, к счастью, речь идет о sql-сервере)

Luuk 25.12.2020 12:12

@Luuk: вопрос помечен как SQL Server, где этот синтаксис поддерживается (хотя я немного удивлен, что он не работает в MySQL).

GMB 25.12.2020 12:15

Я также не ожидал бы, что он потерпит неудачу в MySQL и будет работать в MSSQL. 😎

Luuk 25.12.2020 12:18

@GMB, к сожалению, это не работает, для меня поведение таблицы такое же ..

Houssem Timoumi 25.12.2020 12:25

@HoussemTimoumi: я не понимаю твоего замечания. Какую именно ошибку вы получаете? И в какой базе данных вы выполняете этот запрос (вы отметили вопрос SQL Server, это то, что вы действительно используете?)

GMB 25.12.2020 12:27

@GMB, да, я использую SQL Server 2018, я не получаю сообщения об ошибке, но таблица возвращается с тем же предыдущим содержимым, что означает, что она обычно использует функцию LAG и всегда дает мне предыдущее поле во всех случаях ..

Houssem Timoumi 25.12.2020 12:30

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

GMB 25.12.2020 12:33

Если вам нужна «предыдущая доступность», вы можете сделать это с помощью одной оконной функции и соединения.

select t.*, t2.future_availability
from (select t.*,
             max(case when value_date <> 'reimbursment' then precise_date end) over
                 (order by precise_date
                  rows between unbounded preceding and 1 preceding
                 ) as the_date
      from t
     ) t left join
     t t2
     on t.the_date = t2.precise_date
order by precise_date;

Здесь db<>рабочий пример.

Я ожидаю, что это будет иметь лучшую производительность, чем решение с использованием боковых соединений, предложенное Лууком, особенно с индексом (precise_date).

Другие вопросы по теме