Обновить столбец со значения от последнего значения до следующего заполненного значения - PullRequest
0 голосов
/ 27 июня 2019

У меня есть таблица, которая содержит сумму за месяц и сумму за предыдущий месяц.

Каждый месяц мне нужно нести сумму за предыдущий месяц, если она не существует.

Чтобы объяснить немного лучше (и с примерами), у меня могут быть следующие данные:

Month,Amount,Previous
2019-01-01,100,0
2019-02-01,100,100
2019-03-01,100,null
2019-04-01,100,null
2019-05-01,100,200
2019-06-01,100,null

Итак, я хочу перенести 100 на март и апрель, а затем 200 на июнь, чтобы это выглядело так:

Month,Amount,Previous
2019-01-01,100,0
2019-02-01,100,100
2019-03-01,100,100
2019-04-01,100,100
2019-05-01,100,200
2019-06-01,100,200

Я просто пробиваюсь, я знаю, что есть способ, но разум просто не собирает его.

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

Или он будет выполнять подзапрос в предложении WHERE и LEFT JOIN.

До сих пор я управлял приведенным ниже описанием, но оно дублирует строки мая и июня для каждого предыдущего значения (100 и 200).

SELECT
    *
FROM
    table1 t1
    LEFT JOIN
        table1 t2 ON
            t1.month > t2.month
Month,Amount,Previous
2019-01-01,100,0
2019-02-01,100,100
2019-03-01,100,100
2019-04-01,100,100
2019-05-01,100,200
2019-05-01,100,100
2019-06-01,100,200
2019-06-01,100,100

Ответы [ 3 ]

0 голосов
/ 27 июня 2019

Вы можете использовать коррелированный подзапрос здесь.В подзапросе мы будем использовать ORDER BY с LIMIT, чтобы получить немедленное предыдущее значение суммы.

SELECT
    t1.month, 
    t1.amount, 
    (SELECT t2.amount FROM table1 t2 
     WHERE t2.month < t1.month 
     ORDER BY t2.month DESC LIMIT 1) AS previous 
FROM
    table1 t1
0 голосов
/ 27 июня 2019

В MySL 8+ вы можете использовать оконные функции. К сожалению, MySQL (пока) не реализовал самый простой подход - lag() с опцией ignore nulls.

Но вы все равно можете сделать это довольно просто:

select month, amount, 
       max(previous) over (partition by grp) as previous
from (select t.*, count(previous) over (order by month) as grp
      from t
     ) t;
0 голосов
/ 27 июня 2019
drop table if exists t;
create table t
(Month date,Amount int,Previous int);
insert into t values
('2019-01-01',100,0),
('2019-02-01',100,100),
('2019-03-01',100,null),
('2019-04-01',100,null),
('2019-05-01',100,200),
('2019-06-01',100,null);

select t.*,
        case when previous is null then
            (select previous from t t1 where t1.month < t.month and t1.previous is not null order by month desc limit 1)
        else previous
        end as previousdownfilled
from t;

+------------+--------+----------+--------------------+
| Month      | Amount | Previous | previousdownfilled |
+------------+--------+----------+--------------------+
| 2019-01-01 |    100 |        0 |                  0 |
| 2019-02-01 |    100 |      100 |                100 |
| 2019-03-01 |    100 |     NULL |                100 |
| 2019-04-01 |    100 |     NULL |                100 |
| 2019-05-01 |    100 |      200 |                200 |
| 2019-06-01 |    100 |     NULL |                200 |
+------------+--------+----------+--------------------+
6 rows in set (0.00 sec)

, где инструкция case проверяет, нужно ли что-то делать, и это делает коррелированный запрос cub.Но я подозреваю, что эту работу следует выполнить в коде, который создает эту таблицу.

...