Я хотел бы использовать функцию LAG, чтобы отобразить предыдущую доступную сумму, но когда предыдущая доступная сумма имеет значение_даты «возмещения», она будет продолжать переходить к последнему с типом без возмещения.
Это означает, что LAG следует применять к полю previous_availability следующим образом:
Спасибо!
"...до последнего с безвозмездным типом". Непонятно, как найти этот последний, потому что нет позиции, по которой заказаны эти данные (или эти данные не приведены в заданном вопросе).
Почему «возмещение», которое следует за «использованием», имеет значение 10? Я бы ожидал 6 (предыдущий ряд не возмещение).
@forpas, столбца ID нет, но есть столбец даты, и все записи упорядочены по дате
@GMB, ты совершенно прав!!! я починил это
@Luuk, есть дата, и они упорядочены по дате, я добавил это сейчас!
@HoussemTimoumi: Тогда вы можете использовать мой ответ в качестве основы для своего решения 😉. Удачи в изменении применения его к вашей ситуации!
(ПРИМЕЧАНИЕ: это было опубликовано ДО того, как к вопросу был добавлен 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.
Хорошо, я писал решение для MySQL, а не для MSSQL, моя вина.... 😥
все нормально!!! Вы исправите ответ, пожалуйста?
@HoussemTimoumi: я изменил ответ, чтобы использовать синтаксис MSSQL, а не синтаксис MySQL.
@HoussemTimoumi: в своем комментарии выше измените ASC
на DESC
.
Во-первых: чтобы вопрос имел смысл, вам нужен столбец, определяющий порядок строк — я предположил 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()
.
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: вопрос помечен как SQL Server, где этот синтаксис поддерживается (хотя я немного удивлен, что он не работает в MySQL).
Я также не ожидал бы, что он потерпит неудачу в MySQL и будет работать в MSSQL. 😎
@GMB, к сожалению, это не работает, для меня поведение таблицы такое же ..
@HoussemTimoumi: я не понимаю твоего замечания. Какую именно ошибку вы получаете? И в какой базе данных вы выполняете этот запрос (вы отметили вопрос SQL Server, это то, что вы действительно используете?)
@GMB, да, я использую SQL Server 2018, я не получаю сообщения об ошибке, но таблица возвращается с тем же предыдущим содержимым, что означает, что она обычно использует функцию LAG и всегда дает мне предыдущее поле во всех случаях ..
@HoussemTimoumi: это работает для предоставленных вами данных, как вы можете видеть на скрипке в моем ответе. Если у вас есть конкретная проблема, попробуйте воспроизвести ее в скрипте, а затем поделитесь ссылкой в комментариях.
Если вам нужна «предыдущая доступность», вы можете сделать это с помощью одной оконной функции и соединения.
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)
.
Есть ли такой столбец, как
id
, который определяет порядок строк?