我会迭代地处理这个问题,每一步都规范化表格的一部分。
您应该能够一步将人员数据与地址、状态和 zip 数据进行规范化,然后将状态与地址和 zip 数据进行规范化,最后将 zip 数据与地址的其余部分进行规范化.
作为一个例子,从你问题中的例子开始,这里有一些工作可以做到这一点:
首先,我们应该创建示例数据。我将在本示例中使用 MySQL,但相同的原则适用于任何主要的 RDBMS。
让我们先创建一个空表:
DROP DATABASE IF EXISTS normalisation;
CREATE DATABASE IF NOT EXISTS normalisation
CHARACTER SET utf8 COLLATE utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS normalisation.denormalised (
FirstName VARCHAR(255),
MiddleName VARCHAR(255),
LastName VARCHAR(255),
Address1 VARCHAR(255),
Address2 VARCHAR(255),
City VARCHAR(255),
State VARCHAR(255),
Zip VARCHAR(255)
) ENGINE = INNODB;
我们需要在其中填充一些示例数据,这些数据可以使用 Talend 的 tRowGenerator 组件轻松完成:
我已经配置了 tRowGenerator 来给我们一些半明智的测试输出:
我还添加了一个额外的步骤,使用以下 tMap 配置将一些同居者添加到大约 1/3 的地址:
现在我们已经轻松生成了测试数据,我们可以继续对这个非规范化表中的数据进行实际规范化。
如上所述,我们的第一步是将人员数据标准化。我们首先为人员数据和剩余的地址数据创建必要的表:
CREATE TABLE IF NOT EXISTS normalisation.person (
Person_id BIGINT AUTO_INCREMENT PRIMARY KEY,
FirstName VARCHAR(255),
MiddleName VARCHAR(255),
LastName VARCHAR(255),
Address_id BIGINT
) ENGINE = INNODB;
CREATE TABLE IF NOT EXISTS normalisation.addressStateZip (
Address_id BIGINT AUTO_INCREMENT PRIMARY KEY,
Address1 VARCHAR(50),
Address2 VARCHAR(50),
City VARCHAR(50),
State VARCHAR(50),
Zip VARCHAR(50),
UNIQUE KEY addressStateZip (Address1, Address2, City, State, Zip)
) ENGINE = INNODB;
然后我们通过获取所有地址类型数据来填充这两个表,只获取唯一的行,然后将其放入 addressStateZip 临时表中:
上述工作的第二部分然后将 addressStateZip 数据与初始非规范化表进行比较,并收集连接以获得人员表的 Address_id:
其余步骤现在非常相似。
接下来我们为地址和邮编数据创建状态表和另一个临时表:
CREATE TABLE IF NOT EXISTS normalisation.state (
State_id BIGINT AUTO_INCREMENT PRIMARY KEY,
State VARCHAR(255),
UNIQUE KEY state (State)
) ENGINE = INNODB;
CREATE TABLE IF NOT EXISTS normalisation.addressZip (
Address_id BIGINT AUTO_INCREMENT PRIMARY KEY,
Address1 VARCHAR(50),
Address2 VARCHAR(50),
City VARCHAR(50),
State_id BIGINT,
Zip VARCHAR(50),
UNIQUE KEY addressStateZip (Address1, Address2, City, State_id, Zip)
) ENGINE = INNODB;
现在我们需要从 addressStateZip 表中取出唯一的状态并将它们放入状态表中:
第二部分和之前一样,然后使用 State_id 而不是实际状态将数据创建到 addressZip 临时表中:
现在,最后,我们可以创建 zip 表,然后将其链接到正确的地址表:
CREATE TABLE IF NOT EXISTS normalisation.zip (
Zip_id BIGINT AUTO_INCREMENT PRIMARY KEY,
ZIP VARCHAR(255),
UNIQUE KEY zip (ZIP)
) ENGINE = INNODB;
CREATE TABLE IF NOT EXISTS normalisation.address (
Address_id BIGINT AUTO_INCREMENT PRIMARY KEY,
Address1 VARCHAR(50),
Address2 VARCHAR(50),
City VARCHAR(50),
State_id BIGINT,
Zip_id BIGINT,
UNIQUE KEY addressStateZip (Address1, Address2, City, State_id, Zip_id)
) ENGINE = INNODB;
使用与状态数据相同的方法,我们获取所有唯一的 zip 并将它们放入 zip 表中:
而且,和以前一样,我们现在可以将 Zip_id 放入一个新的、已完成的地址表中:
为了检查,我们现在可以运行以下查询来获取所有数据:
SELECT p.FirstName, p.MiddleName, p.LastName, a.Address1, a.Address2, a.City, s.State, z.Zip
FROM normalisation.person AS p
INNER JOIN normalisation.address AS a ON a.Address_id = p.Address_id
INNER JOIN normalisation.state AS s ON s.State_id = a.State_id
INNER JOIN normalisation.zip AS z ON z.Zip_id = a.Zip_id;
既然您已经完成设置,您可能还想为表添加一些外键约束:
ALTER TABLE normalisation.person
ADD FOREIGN KEY (Address_id) REFERENCES address(Address_id);
ALTER TABLE normalisation.address
ADD FOREIGN KEY (State_id) REFERENCES state(State_id),
ADD FOREIGN KEY (Zip_id) REFERENCES zip(Zip_id);