MySQL/Python - 如何通过向按列添加新值到第一个 NULL 单元格来更新表

问题描述 投票:0回答:2

我是 MySQL 新手。我正在制作一张包含运动员(姓名作为主键)及其跑步时间的表格。

在上一次训练中,Tom 记录为 32 m 46 s,Joe 记录为 34 m 33 s。

我需要一个语句(我使用Python)来更新表格,以便在第一个可用单元格中添加新时间,表格示意图如下:

Name    G1        G2        G3
---------------------------------
Tom     33m21s    31m54s    null
Joe     35m03s    null      null

因此,对于 Tom,时间应位于 G3 列,而对于 Joe,时间应位于 G2 列。

表格应如下所示:

Name    G1        G2        G3
----------------------------------
Tom     33m21s    31m54s    32m46s
Joe     35m03s    34m33s    null

我正在尝试使此任务尽可能自动化,因此我不想每次都指定新时间应该在哪一列中。

我已经尝试过这段代码,但每次都必须指定列: 我不知道“SET”后要插入什么

sqlMP = "UPDATE time SET ...  WHERE player = %s AND G1 IS NULL"

感谢您的帮助

python mysql sql sql-update mysql-python
2个回答
3
投票

您可以按如下方式使用

coalesce()

update time_table set 
    g1 = coalesce(%s, g1),
    g2 = case when g1 is not null and g2 is null then %s else g2 end,
    g3 = case when g1 is not null and g2 is not null and g3 is null then %s else g3 end
where player = %s

请注意,这需要您传递目标值三次。

但是,我建议您这不是存储数据的正确方式。玩家和时间之间是一对多的关系;您应该将每个时间/玩家元组存储在不同的行上。这将大大简化逻辑(新时间只是表中的插入),并避免您将来遇到更多问题(例如:如果您想为每个玩家存储 4 次而不是 3 次怎么办?)。


Gordon L’inoffensif 在他的回答中解释说,在 MySQL 中,在

SET
中执行的更改可以从以下内容中看到 - 因此上述查询将无法按预期工作。

我认为我们可以通过恢复分配顺序来解决这个问题:

update time_table set 
    g3 = case when g1 is not null and g2 is not null and g3 is null then %s else g3 end,
    g2 = case when g1 is not null and g2 is null then %s else g2 end,
    g1 = coalesce(%s, g1)        
where player = %s

1
投票

MySQL 与其他数据库和标准不同,因为当您更新列时,新值会在 set

right
侧可见。请参阅代码后的参考。啊啊啊!

这使得这相当具有挑战性。假设每个名称一行,您可以使用自连接:

update time_table tt join
       time_table ttold
       on tt.name = ttold.name cross join
       (select %s as new_value  -- just a convenience
       ) v
    set tt.g1 = (case when ttold.g1 is null
                      then v.new_value
                      else ttold.g1
                 end),
        tt.g2 = (case when ttold.g1 is null and ttold.g2 is null
                      then v.new_value
                      else ttold.g2
                 end)
        tt.g3 = (case when ttold.g1 is null and ttold.g2 is null and ttold.g3 is null
                      then v.new_value
                      else ttold.g3
                 end);

正如 GMB 指出的,这是一个非常糟糕的数据结构。您应该将值存储在单独的行中,而不是单独的值中。

有关此内容的文档位于此处

以下语句中的第二个赋值将 col2 设置为当前(更新的)col1 值,而不是原始 col1 值。结果是 col1 和 col2 具有相同的值。 此行为与标准 SQL 不同。

UPDATE t1 SET col1 = col1 + 1, col2 = col1;
© www.soinside.com 2019 - 2024. All rights reserved.