从另一列计算的列?

问题描述:

假设表格如下:从另一列计算的列?

id | value 
-------------- 
1  6 
2  70 

有没有一种方法来添加一个基于在同一个表的另一列自动计算列?像VIEW一样,但是是同一张桌子的一部分。作为示例,calculated将是value的一半。 Calculated应该在value更改时自动更新,就像VIEW一样。

其结果将是:

id | value | calculated 
----------------------- 
1  6  3 
2  70  35 
+6

那么,为什么不使用视图? – 2014-11-18 17:44:44

+0

持久性(又名存储)计算列通常更便宜阅读,因为它们与其他列一样存储。他们甚至可以被索引。 – 2017-05-16 22:29:43

+0

非永久计算列只是一个便利功能。在处理ORM时,它通常比视图更好。 – 2017-05-16 22:30:51

如果它是一个选择,你可以做到这一点是:

SELECT id, value, (value/2) AS calculated FROM mytable 

否则,你也可以先改变表添加缺少的列和然后执行UPDATE查询以计算新列的值:

UPDATE mytable SET calculated = value/2; 

如果它必须是自动的,并且哟你可以使用MySQL版本,你可以试试triggers

+6

是的,这是一个SELECT,而不是在表中添加一列。 – Matthew 2011-03-07 16:20:44

+4

您可以使用'calculated'列在相同的查询中运行进一步的计算吗?像('calculate' * 2)AS'double_calculated'? – Piero 2014-11-20 15:14:16

如果你想添加一列到自动更新到其他列的一半的表中,你可以用触发器来实现。

但我认为已经提出的答案是一个更好的方法来做到这一点。

干编码触发:

CREATE TRIGGER halfcolumn_insert AFTER INSERT ON table 
    FOR EACH ROW BEGIN 
    UPDATE table SET calculated = value/2 WHERE id = NEW.id; 
    END; 
CREATE TRIGGER halfcolumn_update AFTER UPDATE ON table 
    FOR EACH ROW BEGIN 
    UPDATE table SET calculated = value/2 WHERE id = NEW.id; 
    END; 

我不认为你只能让一个触发器,因为事件,我们必须响应是不同的。

+0

谢谢。在这种情况下,我们还应该考虑删除? – 2016-07-06 07:03:53

@ krtek的回答是正确的方向,但有几个问题。

坏消息是在同一张表上的触发器中使用UPDATE将不起作用。好消息是没有必要。有一个新的对象,你甚至可以在桌子被触摸之前进行操作。

触发变为:

CREATE TRIGGER halfcolumn_update BEFORE UPDATE ON my_table 
    FOR EACH ROW BEGIN 
    SET NEW.calculated = NEW.value/2; 
    END; 

还要注意BEGIN ... END;语法必须用不同的分隔符生效。整个shebang变成:

DELIMITER | 

CREATE TRIGGER halfcolumn_insert BEFORE INSERT ON my_table 
    FOR EACH ROW BEGIN 
    SET NEW.calculated = NEW.value/2; 
    END; 
| 

CREATE TRIGGER halfcolumn_update BEFORE UPDATE ON my_table 
    FOR EACH ROW BEGIN 
    SET NEW.calculated = NEW.value/2; 
    END; 
| 

DELIMITER ; 
+2

注意:在上面的代码中,将单词“table”替换为您的表名称。我认为作者只是忘记了表名,并在“ON表”之后添加了它,并浪费了几分钟的时间。 – Bloodboiler 2015-12-23 09:31:05

+0

良好的电话@Bloodboiler - 我修改了一小段更清晰的代码片段。 – Jerry 2016-01-14 18:52:54

MySQL 5.7支持计算列。他们称之为“生成的列”,语法有点奇怪,但它支持我在其他数据库中看到的相同选项。

https://dev.mysql.com/doc/refman/5.7/en/create-table.html#create-table-generated-columns

+1

不幸的是,“生成列”不是ISO SQL标准的一部分。看起来像唯一的“ISO SQL”解决方案将是使用VIEW。 – PowerGamer 2015-07-19 08:59:29

生成列是MySQL版本,这是5.7.6及以上的良好的方法之一。

有两种生成列的:

  • 虚拟(默认) - 列将在运行中计算时, 记录从表中读取
  • 存储 - 列将被计算时, 在表中写入/更新新记录

两种类型都可以有NOT NULL限制,但只有存储的生成列可以是索引的一部分。

对于目前的情况,我们将使用存储的生成列。为了实现我都认为,无论是计算所需的值出现在表

CREATE TABLE order_details (price DOUBLE, quantity INT, amount DOUBLE AS (price * quantity)); 

INSERT INTO order_details (price, quantity) VALUES(100,1),(300,4),(60,8); 

量会自动在表中弹出,你可以直接访问它,也请注意,每当您将更新任何列,金额也会得到更新。

+2

我认为这应该是被接受的答案 – 2017-08-04 12:15:14

+0

同意,这是正确的答案。 – 2017-11-16 00:19:55

+0

根据文档,这只适用于NDB存储引擎,而不是InnoDB – cliffordheath 2017-11-30 05:19:09

我希望这仍然可以帮助很多人可能会看到这篇文章的人。如果您需要一个计算列,为什么不在视图中公开您想要的列?不要只保存数据或用触发器重载性能......只需在视图中公开已经格式化/计算出的数据即可。

希望这有助于...