【问题标题】:Update column with value from last value until next populated value使用从最后一个值到下一个填充值的值更新列
【发布时间】:2019-11-09 07:46:40
【问题描述】:

我有一个包含每月金额和上个月金额的表格。

如果不存在,我每个月都需要携带上个月的金额。

为了更好地解释(并通过示例),我可能有以下数据;

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 带到 3 月和 4 月,然后把 200 带到 6 月,所以看起来像这样;

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)复制了 5 月和 6 月的行。

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

【问题讨论】:

  • 您在前几个月加入了所有,而不仅仅是前一个月。

标签: mysql sql min next


【解决方案1】:
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 查询会做。但我怀疑这项工作应该在创建此表的代码中完成。

【讨论】:

  • 嘿,感谢您的建议,但是 CASE SELECT 中的 t.month 无法解析到主查询中的表。你在哪个版本的 MySQL 上试用过这个?
【解决方案2】:

您可以在此处使用Correlated Subquery。在子查询中,我们将使用ORDER BYLIMIT 来获取前一个金额值。

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

【讨论】:

    【解决方案3】:

    在 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;
    

    【讨论】:

    • 嘿,谢谢你的建议,我应该在原始帖子中添加我没有使用新版本的 MySQL,它是一个旧的 5.x 版本,否则我相信 OVER 会是完美的.
    猜你喜欢
    • 2020-10-07
    • 2015-07-22
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    • 1970-01-01
    • 2022-08-03
    • 1970-01-01
    • 2021-08-03
    相关资源
    最近更新 更多