【问题标题】:How to normalize table如何规范化表
【发布时间】:2015-05-24 05:27:45
【问题描述】:

我想我应该首先解释一下系统实际上做了什么以更好地理解。

该系统是一个工资单查看器网站,上传者(人力资源人员)上传一堆 excel 格式的工资单,这些条目会保存到数据库中。然后工资单查看器获取当前登录用户的emp_id,并显示他们所有的earnings, deductions, info 和他们的总earnings(all earnings are added), total deductions(all deductions are added) and netpay(total earning-total deduction)

我的问题是我的教授说我需要“规范化”表格,但我想知道如何才能将其规范化,因为我认为这是“规范化”的。但是,我确实尝试创建两个 erd,但我有几个问题:

  1. 当系统的目的只是读取上传者提供的内容时,我为什么要拆分收入和扣除额?
  2. 我的教授建议我对所有员工进行相同的扣除,但没有这样的事情,我能想到的最接近的一项是保险,它也会根据依赖关系和其他影响它的因素而变化。
  3. 如果我确实尝试创建第 3 项,那么在费率发生变化时会出现问题(即,保险 1 从 2 月开始 = 100 美元在 3 月变为 200 美元)。由于工资单查看器依赖于该表,这意味着如果用户查看他 2 月份的工资单,他的保险费也是 200 美元。
  4. 我正在创建此数据库以符合系统的要求,即上传者上传工资单电子表格,这还不足以证明我的 erd 合理吗?也许如果这是一个工资系统,我可以设置其他表来影响工资单的输出,但是基于系统,输出已经完成,hr 只需要将它们上传到数据库。

我的第一个 ERD:

我的第二个 ERD:

(我这样做是为了尝试使其正常化,但是出于系统的要求,我认为这不合适)

【问题讨论】:

  • 为什么没有单独的扣除表?然后是从 payslip_deduction 到 deduction 的 1-N 关系。
  • @OlleHärstedt 我的第二个 erd 有它。
  • 等等,deductionN是什么字段?
  • 如果每行没有 30 个扣除项,那么您将有多余的字段。您需要按照上面的建议对其进行规范化
  • "(我这样做是为了使其正常化,但出于系统的要求,我认为这不合适)"你大错特错了。

标签: mysql data-modeling database-normalization


【解决方案1】:

据我所知,您似乎非常接近,您只需将扣除额和收入表的关系更改为一对多,并删除所有多余的“收入”和“扣除”列,留下您带有以下内容:

通过这种方式,您可以根据需要拥有与工资单相关联的尽可能多的收入记录和扣除记录。

【讨论】:

  • 我主张将收入和扣除表结合起来,并添加一个额外的字段,以便您知道它是收入还是扣除。最后,这一切都只是逐项列出的工资单,它们的属性是相同的。
  • 哇,这是一个非常好的答案,我没有想过这个,但现在这比我以前的 erd 更有意义。我更专注于通过列显示每个收入/扣除额,而实际上它们可以在行上。我想我的问题是我创建了带有完整首字母缩略词的 erd,现在我已经将它们更改为 deduction1、deduction2 它更清楚地表明它们应该在行上,我可以创建另一列来存储它们的首字母缩略词。跨度>
  • arghhh 让我很痛苦,因为我的声望很低,所以我不能提高这个水平,但我想提醒读者这应该是 ERD(尽管应该合并)。
【解决方案2】:

我的猜测是您的教授希望您不要有 30 个扣除字段。比如......当你摆好桌子并发现自己在做:

object_typa_1 | object_typa_2 | object_typa_3 | object_typa_4 | object_typeb_1 | object_typeb_2 ..

并将值存储在各自的字段中。相反,您应该规范化,以防有一天您必须添加deduction31,您不必执行 ALTER TABLE 并围绕所有 SQL 进行调整以适应。

改为:

Object Table:
type | number | value

在你的情况下:

employees:
emp_id | password | name | ...

payslips:
id | emp_id | other payslip attributes | ...


payslip_items:
payslip_id | type  | number | value

在 payslip_items 表中,您为每个工资单粘贴了多条记录。您在type 字段中告诉它该项目是收入还是扣除。你说它在那个number 字段中是哪个收入或扣除额......可能不是最好的名字,但例如很好。然后是value 字段中的收入/扣除值。因此,实际上,您的 payslip_items 表将包含每个工资单的 34 条记录(30 条扣除和 4 条收入)...

您想要这样做的原因是,在现实世界中,一旦您为客户/业务合作伙伴推出这个东西,他们就会想要在工资单上添加新的扣除额或收入(保证)。此模式有效,因为您不必更改表并弄乱所有处理 payslip_items 的 sql。它会根据您的需要增长和缩小。

【讨论】:

  • 好点,我的查询可以选择所有收入、扣除和添加。这似乎更好,尽管由于系统的限制,特别是读取这些电子表格的 payslip reader 功能,它仍然会受到限制,因为我需要重新编码 payslip reader 以读取保存该值的特定单元格并且只是提醒一下,他们上传的工资单不是很干净,它们被格式化为正常的工资单应该显示(即 deduction1 在 c2 deduction2 在 d5 上)。
  • 但总的来说,这是一个非常好的答案,尽管这个解决的问题仍然受到系统限制(只能读取固定单元格目的地)的限制,但它可能会让 erd 被接受。
  • 我认为您面临的问题最好在前端解决,以及如何将其连接/翻译到数据库。您只需要遍历作为扣除/收入的每个单元格,并为每个命中插入一条新记录。
  • 另外,@nullReference 的 ERD 几乎显示了我在这里提倡的内容。我只是更进一步,将您的扣除表和您的第二个 ERD 中的收入表结合起来,然后进行非规范化。我也会制作 ERD……但这需要我一天的时间,因为我对那种软件很感兴趣。线条、正方形和关系……啊!
【解决方案3】:

我认为下面的表格结构可以解决您的问题。

CREATE TABLE `Emp` (
    `id` int NOT NULL,
    `name` varchar(100) NOT NULL,
    `password` varchar(255) NOT NULL,
    `user_type` varchar NOT NULL,
    PRIMARY KEY (`id`)
);

CREATE TABLE `payslip_map` (
    `id` INT NOT NULL AUTO_INCREMENT,
    `emp_id` INT NOT NULL,
    `payslip_id` INT NOT NULL,
    PRIMARY KEY (`id`)
);

CREATE TABLE `payslips` (
    `id` INT NOT NULL,
    `particular_id` INT NOT NULL,
    `amt` FLOAT NOT NULL
);

CREATE TABLE `particulars` (
    `id` INT NOT NULL AUTO_INCREMENT,
    `particulars` varchar(80) NOT NULL UNIQUE,
    `is_earning` BOOLEAN NOT NULL,
    PRIMARY KEY (`id`)
);

ALTER TABLE `payslip_map` ADD CONSTRAINT `payslip_map_fk0` FOREIGN KEY (`emp_id`) REFERENCES `Emp`(`id`);

ALTER TABLE `payslip_map` ADD CONSTRAINT `payslip_map_fk1` FOREIGN KEY (`payslip_id`) REFERENCES `payslips`(`id`);

ALTER TABLE `payslips` ADD CONSTRAINT `payslips_fk0` FOREIGN KEY (`particular_id`) REFERENCES `particulars`(`id`);

视觉呈现

【讨论】:

  • use text, not images/links, for text--including tables & ERDs。转述或引用其他文本。只提供您需要的东西并将其与您的问题联系起来。仅将图像用于无法表达为文本或增强文本的内容。无法搜索或剪切和粘贴图像。在图像中包含图例/键和说明。 PS没有解释这是一个糟糕的答案。此外,它不会为其他答案添加任何内容。 How to Answerhelp center
  • 感谢您的回复。添加了 Mysql Schema 以及可视化演示。
猜你喜欢
  • 2012-04-06
  • 2011-03-08
  • 2012-09-01
  • 1970-01-01
  • 2011-05-09
  • 2021-11-07
  • 2016-07-08
  • 1970-01-01
  • 2012-12-31
相关资源
最近更新 更多