如何链接包含不同列和ID的相同产品的许多表

时间:2014-12-28 20:01:29

标签: mysql sql database-design

我有来自不同供应商的许多表格,其中包含有关他们提供的产品的信息。表的格式是不同的 - 不同的ID,不同的描述等 - 因为每个供应商存储关于其产品的单独信息。不同表格中的某些产品可能相同,但我不知道插入行时的情况;我必须手动完成它们以确定哪些产品是相同的。

例如,请考虑以下表格(SQL Fiddle):

CREATE TABLE A (
  id char(10)PRIMARY KEY,
  name char(16),
  color char(16),
  weight float
  );

CREATE TABLE B (
  id int(11) PRIMARY KEY,
  name varchar(60),
  color char(3)
  );

每个表可能具有不同的ID值,列,甚至同一列的值; e.g:

Table A:
+------------+-----------------+---------------+-----------------+
|         ID |            NAME |         COLOR |          WEIGHT |
+------------+-----------------+---------------+-----------------+
| RFY-55-001 |  Wagon, Classic |           Red | 15.199999809265 |
| RFY-62-001 | Trike, My First |           Red |   8.60000038147 |
| RFY-64-001 |  Trike, 12 Inch |           Red |  15.39999961853 |
| SWN-35-001 | Trike, Roadster | Metallic Blue | 20.700000762939 |
| SWN-35-002 | Trike, Roadster |        Silver | 20.700000762939 |
| SWN-35-003 | Trike, Roadster |    Cherry Red | 20.700000762939 |
+------------+-----------------+---------------+-----------------+

Table B:
+-------+--------------------------------------------+--------+
|    ID |                                       NAME |  COLOR |
+-------+--------------------------------------------+--------+
| 10560 |                  Schwinn Roadster Tricycle |    BLU |
| 10685 |              Radio Flyer Classic Red Wagon | (null) |
| 10880 | Radio Flyer Classic Red Dual Deck Tricycle | (null) |
| 12008 |         Fisher-Price I Can Play Basketball | (null) |
+-------+--------------------------------------------+--------+

供应商A存储简短的产品名称,但在其他列中包含详细的产品信息。供应商B存储更详细的产品名称,但没有更多的附加信息。在这两种情况下,制造商的身份都会混合到其他领域。

自动插入行,我无法在插入之前检查每个产品。我只能偶尔检查它们并更新我手动找到的链接。例如,一项小小的研究表明,Radio Flyer经典红色双层三轮车有一个12"前轮,重15.4磅,表示表A中的项目RFY-64-001与表B中的项目10880是相同的产品。

我会用什么关系来链接"不同表格中的行,如果它们引用相同的产品,在插入它们之后,那么每个独特的产品都会有一个键?

显而易见的解决方案是使用我的密钥添加连接表,并在插入其他表时使用触发器。这个解决方案的问题在于"同步"过程变得非常手动,容易出错。

2 个答案:

答案 0 :(得分:20)

好;因此,您有许多源自不同来源的表,每个表都使用自己的逻辑结构实现相同的实体(Product)。任何给定的记录可能存在于多个表中,您的任务是协调这些不同的数据源,使用一些手动过程来确定哪些记录在表中相似/相同。

这听起来类似于我们在Cal / EPA进行的一个过程,用于协调来自许多不同来源的数据,以创建全州范围的空气污染清单。这些来源包括几个不同的建模团队,每个团队使用一组不同的输入和输出参数;监测站的直接测量;地方和市政机构的年度报告;在某些情况下,个人和企业直接向我们报告的数据。这些数据以许多不同的格式呈现给我们,其中大部分都是重叠的。

我对你和解过程的细节不满意,但我可以告诉你一些我从中学到的东西,并建议一种可能适合你的方法。

首先,将以多种不同格式存在的重叠数据放在一起糟透了。如果每个人都使用相同的桌面结构并且彼此远离彼此,那么我们的工作就会容易得多。那就是说,这是我们必须应对的现实;这就是为什么我们有工作。不同的组织和个人的运作方式不同,期间和大多数时候你都没有权力改变他们的运作方式。

你需要一个计划,否则将犯错误 - 不是偶然的错误,而是常数错误。您可以采取的一种广泛的方法是:我将接受来自所有这些格式的数据,并将其放入一个临时数据库中,在那里我将根据需要操作和聚合并剪切和拍打和破坏数据以使其适合我的闪亮的,表现良好的数据库,其中只有一个物理模型,一切都很棒。然后我可以忘记我对数据所做的所有无法形容的事情,以便首先将它放在那里,生活将是美好的...直到我必须重新做到这一点。这称为 ETL ,代表提取,转换,加载 - 或者可能包含Entrap,Torture,Lobotomize,具体取决于您拥有多少乐趣。如果您愿意,可以read about it on Wikipedia(或here on SOhere on DBA.SEthis guide from a company that knows a thing or two about torture)。

关于ETL的好处是你最终会感觉良好。关于ETL的不太好的事情是,通过转换数据以满足您的特定需求,您经常会丢失源中存在的某种程度的细节或实用程序。另一方面,如果您创建一个高度通用的数据模型,以便尽可能多地捕获源数据并避免破坏性转换,那么最终会得到一个高度通用的数据模型,这意味着即使您的文档和维护工作也更多模型是完美的 - 它永远不会。

现在,听起来您不愿意或无法转换您的源数据以适应合理关注的模型。并且你不应该把它全部塞进一个充满重复列和NULL的表中,以免你疯狂地迅速下降到他家里的Cthulhu的幻想中,并且在R' lyeh:

+-----+---------+------------+---------+-----------------+-------------+-----+
| id  | sup1_id | sup1_color | sup2_id | sup2_color      | sup2_weight | ... |
+-----+---------+------------+---------+-----------------+-------------+-----+
| 1   | 7124    | brn        | 93      | Burnt Sienna    | 0.65        | ... |
| 2   | 415     | yel        | 8552    | Bananas Foster  | 12.50       | ... |
| 3   | NULL    | NULL       | 51      | Mostly Red      | 2.00        | ... |
| 4   | 159     | wht        | NULL    | NULL            | NULL        | ... |
| 5   | NULL    | NULL       | NULL    | NULL            | NULL        | NULL NULLNULLNULLUNNLUNUL gratuitous Unicode diacritics, you get the idea

根本不属于关系数据库;它是一个平面文件/电子表格范例,应该限制在像Excel这样的非数据库环境中。 (或访问。 Zing!

如果您需要以各种形式保留不同的表格,但仍希望彼此关联并保留某种" master&# #34;记录,正在创建其他表来表征这些关系,并存储您的一键来统治它们。"现在我们正朝着谈论子类型和角色的方向前进。您有一个以各种方式表示的实体(产品);如果产品的每个实例只存在一个表示,那么您将处理实体子类型。在存在重叠的情况下,就像在这里一样,考虑实例可以对每个供应商采取的角色更好。以下是Data Modeling, A Beginner's Guide的一个例子:

你的"主人" ID和任何相关信息都属于左侧的关系,我只称之为Product。无论供应商是谁,您都希望存储对于给定产品始终相同的属性;或者,"官方"您知道的属性版本因供应商而异,如果需要的话。例如,如果您是制造商,则产品的MSRP不依赖于携带产品的零售商;它应该在主表中。它也可以作为一个官员"价格与不同零售商的各种定价相反。

您的各种供应商表位于右侧。这些是产品所扮演的角色;这里将存储您希望能够在供应商之间变化的任何信息(在您的示例中,产品颜色)或与某些供应商相关联的信息,而不是其他供应商(在您的示例中,重量)。由于产品和角色之间存在多对多关系,因此在它们之间添加一个联结表,其中分配了角色;如果您没有保留历史记录,则不需要在联结表中设置日期,如上图所示,但这是关于角色分配的信息的示例< / em>适合存储在联结表中。

由于您指定需要在之后将供应商表中的记录链接起来,通过您的神秘手动流程,您在此方法下的工作流程可能类似于:< / p>

  1. 将记录插入各种供应商表格。
  2. 您注意到已插入新记录(此处有触发器可能有用的地方)。
  3. 使用神奇的神秘手动过程,您可以确定产品中是否存在每条新记录。
  4. 每当产品中不存在供应商的新记录时,您都会在Product中插入一个新行,以唯一标识(并可能表征)该项目。
  5. 您为来自供应商的每条新记录在联结表中插入一个新行,将该项目的唯一记录链接到表明其与该供应商的角色的其他信息。
  6. 请注意,由于您的外键将位于联结表中,因此可能没有角色/供应商的产品以及没有产品的供应商。至于跟上工作流程并避免错误,除非您已准备好向我们提供有关您在供应商表之间链接产品的流程的更多信息,我建议的最佳方法是在每个表上使用AFTER INSERT个触发器供应商表格中将表格的名称和行的PK放入一个跟踪新产品的表格中,直到他们完成手动链接过程,并在您进行手动链接时删除这些行过程

    您可以在联结表上使用另一个触发器来清除新的/未链接的产品表,但更新或删除行的触发器风险更大。实际上,如果您可以使用应用程序逻辑而不是触发器来填充新的/未链接的产品表,那么这也是可取的。您可以通过博客Triggers Considered Harmful, Considered Harmful阅读有关触发器辩论双方的深思熟虑的分析,尽管它并不是针对MySQL的。

答案 1 :(得分:-1)

我会使用您自己的主键(id)创建一个主产品表。

create table product_master (
product_id INTEGER(11) NOT NULL AUTO_INCREMENT,
product_name varchar(512),
...
);

然后我会在每个供应商表中添加一个新字段。

alter table a add product_id integer(11);
alter table b add product_id integer(11);
...

理想情况下,您将product_master表中的product_id定义为主键,并将其定义为供应商表中的外键。

使用第一个供应商的内容填充产品主数据,然后通过GUI将每个产品链接到现有产品或新产品主数据。不要忘记创建一个选项&#34; merge&#34; 2产品大师分为1,以防万一你太晚意识到2个产品实际上是相同的。

如果大多数产品不同,您可以使用每个供应商的内容填充产品主数据,然后使用合并功能合并2个产品。

产品与product_id 45和555的合并意味着: 1)在每个供应商表中将product_id从45更新到555 2)删除产品主表中的条目555

显然,您需要一个GUI来有效地执行此任务。