【问题标题】:SQL update a calculated column [closed]SQL更新计算列[关闭]
【发布时间】:2016-04-19 18:06:29
【问题描述】:

我的表中有一个列需要更新。该列的计算方式如下:

SELECT CASE WHEN TIMESTAMPDIFF(YEAR, geburtstag, NOW()) <= 27 THEN ((w_staerke/100*70) + (w_technik/100*30))
            WHEN TIMESTAMPDIFF(YEAR, geburtstag, NOW()) <= 31 THEN ((w_staerke/100*70) + (w_technik/100*30))
       END AS marktwert
FROM _spieler;

我想更新该表中所有记录的列。

我可以使用类似的东西

UPDATE _spieler SET marktwert = CASE WHEN TIMESTAMPDIFF(YEAR, geburtstag, NOW()) <= 27 THEN ((w_staerke/100*70) + (w_technik/100*30))
                WHEN TIMESTAMPDIFF(YEAR, geburtstag, NOW()) <= 31 THEN ((w_staerke/100*70) + (w_technik/100*30))
           END;

查询似乎是正确的,但是它将每一行的“marktwert”中的值设置为零。

CREATE TABLE `_spieler` (
  `id` int(10) NOT NULL,
  `vorname` varchar(30) DEFAULT NULL,
  `nachname` varchar(30) DEFAULT NULL,
  `geburtstag` date NOT NULL,
  `w_staerke` tinyint(3) NOT NULL,
  `w_technik` tinyint(3) NOT NULL,
  `marktwert` int(10) NOT NULL DEFAULT '0',
  `age` tinyint(3) DEFAULT NULL,
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=535 ;

(1, 'Adam', 'Federici', '1985-01-31', 30, 20, 0, NULL),
(2, 'Ryan', 'Allsop', '1992-06-17', 20, 30, 0, NULL),
(3, 'Tyrone', 'Mings', '1980-03-13', 40, 20, 0, NULL),
(4, 'Joe', 'Bennett', '1990-03-28', 25, 30, 0, NULL),
(5, 'Charlie', 'Daniels', '1986-09-07', 50, 30, 0, NULL);

表定义和一些示例数据

UPDATE _spieler 
SET marktwert = CASE WHEN TIMESTAMPDIFF(YEAR, geburtstag, NOW()) <= 27 THEN ((w_staerke/100*70) + (w_technik/100*30)) * 600000 
WHEN TIMESTAMPDIFF(YEAR, geburtstag, NOW()) <= 31 THEN (((w_staerke/100*70) + (w_technik/100*30)) * 600000) - 5000000 
WHEN TIMESTAMPDIFF(YEAR, geburtstag, NOW()) > 31 THEN (((w_staerke/100*70) + (w_technik/100*30)) * 600000) - 10000000 END

添加了最终查询

【问题讨论】:

  • 你确定SO是SQL教程吗?
  • 伙计们,他是新来的,我建议他在旧问题的基础上创建一个新问题。我想他有点赶时间并发布了这个配方不佳的帖子。我完全重写了它以添加一些上下文。你能收回你的反对票,这样他将来​​就不会气馁寻求帮助吗? :))
  • 他们是对的,我为此道歉,真的应该花点时间。即使有点跑题了,我还是想再次感谢 Tudor 的理解和耐心,这在当今真的很少见
  • 好的,我删除了反对票,现在你编辑了它,至少它有一些意义,Saint-Tudor ;)
  • "是否可以使用上面创建的别名中的值..?" - 您可以使用 VIEW(查看更新的答案)。

标签: mysql sql


【解决方案1】:

您的问题是您没有为 31 岁以上的玩家 (Spieler) (geburtstag = 生日) 计算任何 marktwert 值。您的 UPDATE 语句正在尝试将NULL 写入marktwert 列,该列定义为NOT NULL。这会导致错误。

解决方案:

1) 用户ELSE 在您的CASE 语句中设置一个默认值:

UPDATE _spieler SET marktwert =     CASE 
        WHEN TIMESTAMPDIFF(YEAR, geburtstag, NOW()) <= 27 THEN ((w_staerke/100*70) + (w_technik/100*30))
        WHEN TIMESTAMPDIFF(YEAR, geburtstag, NOW()) <= 31 THEN ((w_staerke/100*70) + (w_technik/100*30))
        ELSE 0
    END;

2) 允许NULL 列marktwert 的值:

CREATE TABLE `_spieler` (
  ...
  `marktwert` int(10) NULL DEFAULT '0',
  ...
)

3) 使用WHERE 条件:

UPDATE _spieler SET marktwert =     CASE 
        WHEN TIMESTAMPDIFF(YEAR, geburtstag, NOW()) <= 27 THEN ((w_staerke/100*70) + (w_technik/100*30))
        WHEN TIMESTAMPDIFF(YEAR, geburtstag, NOW()) <= 31 THEN ((w_staerke/100*70) + (w_technik/100*30))
    END
WHERE TIMESTAMPDIFF(YEAR, geburtstag, NOW()) <= 31;

更新:您还可以删除 marktwert 列并改用 view(计算表):

CREATE VIEW `_spieler_view` AS SELECT s.*,
    CASE 
        WHEN TIMESTAMPDIFF(YEAR, geburtstag, NOW()) <= 27 THEN ((w_staerke/100*70) + (w_technik/100*30))
        WHEN TIMESTAMPDIFF(YEAR, geburtstag, NOW()) <= 31 THEN ((w_staerke/100*70) + (w_technik/100*30))
    END AS marktwert_calculated
from _spieler s ;

更新 2:

如果你使用 MariaDB,你也可以使用 Virtual (Computed) Columns

【讨论】:

  • 所以我试图简化我的查询实际上导致了问题。非常感谢,终于完成了:)当然还有其他(试图)提供帮助的人!
  • 我刚刚意识到在某些情况下我得到了 marktwert 的负值。是否可以说所有负值都应自动更改为值 1?解决方案 1 实际上效果最好,感谢您的努力!
  • 负值怎么可能? w_staerke 或 w_technik 必须为负数。是这样吗?
  • 该死,我的错。我现在将要使用的实际查询编辑到上面帖子的底部。如果玩家达到一定年龄,我会减去一定数量的价值,这实际上是 CASE 使用的重点
  • 随着您的更新,它变成了另一个问题。但是 - 我会处理您的应用程序中的负值。伪代码:if marktwert &lt; 0 then marktwert = 1; - 对于任何程序员来说都应该是微不足道的。但是 SQL 中的解决方案要么需要子查询,要么需要更复杂的条件(SQL 不是过程式的)。
猜你喜欢
  • 2021-09-14
  • 1970-01-01
  • 2019-07-02
  • 1970-01-01
  • 2013-04-11
  • 2010-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多