我们有一个单一的源表,它是扁平的——我们需要将给定记录中的不同字段插入到多个表中。我们成功地使用了一次lastInsertID,但我们正在努力解决如何在后续相关表中再次从同一源行重新添加字段。
例如,如果我们有一个邮寄地址(即将出现的愚蠢示例,但适合共同讨论)
-----------Source----------
First Name
Middle Name
Last Name
Address 1
Address 2
City
State
Zip
-----------Targets-------------
People
address_id
First Name
Last Name
Address
address_id
state_id
zip_id
Address 1
Address 2
States
state_id
State Name
Zip
zip_id
Zip Code
此外,我们无法确定是否不需要将同一列添加到多个表中。
Talend 中这种数据标准化的最佳实践是什么?
最佳答案
我会迭代地处理这个问题,每一步都对表的一部分进行标准化。
您应该能够一步将个人数据从地址、州和邮政编码数据中标准化,然后将州从地址和邮政数据中标准化,最后将邮政数据从地址的其余部分中标准化.
作为一个例子,按照您问题中的示例,这里有一些工作可以做到这一点:
首先,我们应该创建示例数据。我将在本示例中使用 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 数据与初始非规范化表进行比较,并收集连接以获取 person 表的 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 临时表中:
现在,我们终于可以创建邮政编码表,然后将其链接到正确的地址表:
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_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);
关于etl - Talend 将平面文件规范化为关系数据库表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27391606/