【问题标题】:mysql: set column to value from previous row based on another column's valuemysql:根据另一列的值将列设置为上一行的值
【发布时间】:2018-03-15 07:11:47
【问题描述】:

尝试执行以下操作:如果当前行的列 c1 等于前行的 c1,则将列 c3 设置为前行的列 c2;否则,将 c3 设置为 NULL(或者不将其设置为任何值)。有人能告诉我为什么以下查询导致 c3 对于每一行都为空吗?

虚拟列只是为了能够设置变量@c1 和@c2,它们应该存储该行的c1 和c2 值以用于下一行。顺便说一句,我假设 c3 将首先更新是错误的吗,即它将获得 @c2 的先前值(在 @c2 被分配给当前 c2 之前)?

UPDATE t SET c3 = IF (c1 = @c1, @c2, NULL), dummy1 = @c1:=c1, dummy2 = @c2:=c2;

【问题讨论】:

    标签: mysql variable-assignment user-variables


    【解决方案1】:

    我试过了,它似乎工作正常。但如果您需要按特定顺序评估行,则需要 ORDER BY

    create table t (c1 int, c2 int, c3 int, id int auto_increment primary key);
    
    insert into t (c1, c2, c3) values
     (1, 2, 3),
     (1, 4, 5),
     (2, 6, 7);
    
    select * from t;
    +------+------+------+----+
    | c1   | c2   | c3   | id |
    +------+------+------+----+
    |    1 |    2 |    3 |  1 |
    |    1 |    4 |    5 |  2 |
    |    2 |    6 |    7 |  3 |
    +------+------+------+----+
    
    update t set c3=if(c1=@c1,@c2,NULL), c1 = @c1:=c1, c2 = @c2:=c2 order by id;
    Query OK, 3 rows affected (0.02 sec)
    Rows matched: 3  Changed: 3  Warnings: 0
    
    select * from t;
    +------+------+------+----+
    | c1   | c2   | c3   | id |
    +------+------+------+----+
    |    1 |    2 | NULL |  1 |
    |    1 |    4 |    2 |  2 |
    |    2 |    6 | NULL |  3 |
    +------+------+------+----+
    

    请注意,我不需要虚拟列。只需设置 c1=c1 和 c2=c2,因为它们是无操作的。

    【讨论】:

    • 是的,我完全忘记了订单 - ORDER BY id, c1 为我工作!关于不需要虚拟列的好点。谢谢!
    • 只是好奇为什么单独ORDER BY id 不能为我做这件事——有什么想法吗? AFAIK,两列中都没有空值(已经关闭,但会在早上检查)。
    • 由于每个 id 值有多个行,因此存在平局,并且具有相同 id 的行的顺序是不可预测的。抱歉,我在回答中忘记了这一点。
    • 嗯,但 id 是一个(唯一的)主键,无论是在你的表中还是我的表中。这是更大的谜团:我有这个表的 2 个版本,开发和生产。据我所知,它们在一定程度上是相同的,之后开发停止并且生产具有更多相同类型的数据。我第一次在 dev 上运行查询时,它更新了 0 行。然后我添加了, c1,它似乎工作正常。现在我在生产中使用ORDER BY id, c1 运行查询 - 再也没有!我再次运行相同的确切查询,它有效?!?所以这根本不是, c1,而仅仅是重新运行查询的事实??
    • 如果没有看到您的表定义,我无法猜测。无论如何,这是一个总是很棘手的问题,因为在 SQL 中,行不应该具有任何隐式顺序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 2018-12-11
    • 1970-01-01
    • 1970-01-01
    • 2014-06-27
    相关资源
    最近更新 更多