不应在表中存储计算值。这违反了数据库规范化,因为您会冗余存储值。示例:如果一个表包含x和y列以及x_+y列,并且它们在表行中的值是10、12和13,那么某个人或进程插入了无效数据,因为10+12=22,而不是13。也许一开始这些值是正确的,但后来其中一个值被更新了,更新人员或流程也不知道他们必须更新依赖列。不管怎样,现在一些查询可能使用x_加y,而另一些查询可能使用x和y计算结果,因此它们给出不同的结果。这绝对不是问题。
解决方法是:不要存储这些值,因为你总是可以临时计算它们。但是,您可以编写视图或将生成的列添加到表中。生成的列仅仅是在查询时或基值更改时完成的计算。例如。
create table io_generated
(
...
total_late decimal(10,2) generated always as (late1 + late2 + late3 + late4) virtual;
...
);
(规则的例外:在数据仓库中,我们通常接受冗余。我们通常从数据库中获取数据而不使用冗余,并引入冗余以提高访问速度。)
除此之外,你的桌子看起来还不错。然而,我们无法知道它的设计是否合适,因为我们对您的数据知之甚少。更典型的设计是:
CREATE TABLE io_generated
(
io_generated_id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
employee_id INT(11) UNSIGNED NOT NULL,
date DATE NOT NULL,
branch_id MEDIUMINT(8) UNSIGNED NOT NULL
);
CREATE TABLE io_detail
(
io_detail_id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
io_generated_id INT(11) NOT NULL,
in_datetime DATETIME NOT NULL,
out_datetime DATETIME NOT NULL,
in_branch_id MEDIUMINT(8) UNSIGNED NOT NULL,
out_branch_id MEDIUMINT(8) UNSIGNED NOT NULL,
in_edited TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
out_edited TINYINT(1) UNSIGNED NOT NULL DEFAULT 0
);
与你的设计相比,这种设计有优点也有缺点。
-
例如,在晚上10点之后判断是否有IOs是非常容易的,因为这只是我们必须查看的一个数据库列。另一方面,很难判断第三个IO在晚上10点之后是否有IOs,因为我们必须首先确定哪个细节行是第三个。
-
这很容易扩展,将来有五台IOs,而不是只有四台。只需添加一行;我们根本不需要改变桌子的设计。另一方面,很难或不可能保证有四个IOs。
-
很容易计算出涉及到多少不同的in分支(
COUNT(DISTINCT in_branch_id)
).
-
不可能保证所有细节行的日期都与父行的日期匹配。然而,这可以通过从代理关键点切换到自然复合关键点来轻松解决。
我希望这能帮助你了解当决定一个设计或另一个设计时该考虑什么。