我正在努力升级MySQL数据库的架构,该数据库存储人员及其相关的慈善机构列表。问题表Persons
中包含个人数据和相关慈善机构。它包含以下字段:
如果需要,以下是上述DDL:
CREATE TABLE `Persons` (
`Person_Id` SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`Citizen_Id` CHAR(10) NOT NULL UNIQUE COMMENT 'a unique alphanumeric national id',
`Person_Full_Name` CHAR(100) NOT NULL,
`Person_Email` CHAR(50) NULL,
`Person_Assistant_Contact` CHAR(20) NULL COMMENT 'the cellphone of the persons personal assistant',
`Charity_Org_Id` SMALLINT UNSIGNED NOT NULL COMMENT 'foreign key for a master table of charitable organizations',
`Designation_Id` SMALLINT UNSIGNED NULL COMMENT 'foreign key for a master table of designations that the person can hold in the charitable organization',
FOREIGN KEY (`Charity_Org_Id`) REFERENCES `Charity_Orgs` (`Charity_Org_Id`),
FOREIGN KEY (`Designation_Id`) REFERENCES `Designations` (`Designation_Id`),
) ENGINE = INNODB;
由于有许多人参与多个慈善组织,因此该表有许多条目,其中名称和联系信息相同,但Charity_Org_Id和Designation_Id不同。 INSERT查询示例(请注意第一列和最后两列):
INSERT INTO `Persons` VALUES
(2387,'OZN13445','Frederick Oznawa','info@oznawaind.org','+54-332887789',128,12),
(4533,'OZN13445','Frederick Oznawa','info@oznawaind.org','+54-332887789',520,2),
(4555,'OZN13445','Frederick Oznawa','info@oznawaind.org','+54-332887789',522,4);
显而易见的一步是将联系信息和相关的慈善机构分成不同的表格。这就是我想要的:
INSERT INTO `Persons` VALUES
(2387,'OZN13445','Frederick Oznawa','info@oznawaind.org','+54-332887789');
INSERT INTO `Person_Charities` VALUES
(2387,128,12),
(2387,520,2),
(2387,522,4);
获取新的Persons
表非常简单。 我希望有一个纯粹的SQL解决方案来获取' Person_Charities'表(我想使用每人最低的Person_Id并丢弃剩余的ID)。我可以使用电子表格软件手动执行此操作,但这很容易出错,我正在查看数千行。
注意:我不想将Citizen_Id用作替代主键
答案 0 :(得分:1)
您可以使用以下查询查询要分隔的列的不同列表:
SELECT
MIN(`Person_Id`) AS Person_Id
`Citizen_Id`,
`Person_Full_Name`,
`Person_Email`,
`Person_Assistant_Contact`
FROM
Persons
GROUP BY
`Citizen_Id`,
`Person_Full_Name`,
`Person_Email`,
`Person_Assistant_Contact`assistant'
好的,我们有一个查询来获取您桌子上的人员的明确列表。
创建新表格
您可以使用CREATE TABLE ... SELECT
语法创建表,也可以创建一个新表来存储数据,并使用INSERT ... SELECT
语法根据上述查询插入不同的人。我个人更喜欢手动构建一个新表。
CREATE TABLE `New_Persons` (
`Person_Id` SMALLINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`Citizen_Id` CHAR(10) NOT NULL UNIQUE COMMENT 'a unique alphanumeric national id',
`Person_Full_Name` CHAR(100) NOT NULL,
`Person_Email` CHAR(50) NULL,
`Person_Assistant_Contact` CHAR(20) NULL COMMENT 'the cellphone of the persons personal assistant'
);
将数据插入我们的全新表格
INSERT INTO New_Persons (
Person_Id,
Citizen_Id,
Person_Full_Name,
Person_Email,
Person_Assistant_Contact
)
SELECT
MIN(Person_Id) AS Person_Id,
Citizen_Id,
Person_Full_Name,
Person_Email,
Person_Assistant_Contact
FROM
Persons
GROUP BY
Citizen_Id,
Person_Full_Name,
Person_Email,
Person_Assistant_Contact;
很好,我们有一张不同人士的桌子。如果您愿意,可以添加其他约束和索引。
如何继续?
我们有一个表格,其中包含不同的人(即:New_Persons
)和一张表格,其中包含原始Persons
表格中的(几乎)相似人物数据。下一步是减少旧的Persons
表以仅存储所需的信息。
选项包括:
New_Persons
表中的ID,然后使用Multiple-table update查询更新该列,然后删除不必要的列。如果您有足够的存储空间,我建议您使用第二个选项。您可以验证插入的数据是否正常,并且您不需要完全重新组织旧表。最重要的是,丢失任何数据的机会要少得多(因为你没有触及现有的表,所以你可以在出现问题时重新启动这个过程。)
创建新表格
CREATE TABLE `Person_Charities` (
`Person_Id` SMALLINT UNSIGNED,
`Charity_Org_Id` SMALLINT UNSIGNED NOT NULL COMMENT 'foreign key for a master table of charitable organizations',
`Designation_Id` SMALLINT UNSIGNED NULL COMMENT 'foreign key for a master table of designations that the person can hold in the charitable organization',
PRIMARY KEY PK_PersonCharities (Person_Id, Charity_Org_Id)
);
再次,你可以调整键,索引和你想要的任何东西。
将数据插入新表格
所以,我们有一个新表是空的,两个旧表有一些数据,我们知道它们之间的关系。我们现在的目标是创建一个查询,以从旧的Persons
表中检索新的Person_id和剩余列。
这听起来像使用除Person_Id
INSERT INTO Person_Charities
(
Person_Id,
Charity_Org_Id,
Designation_Id
)
SELECT
NP.Person_Id,
P.Charity_Org_Id,
P.Designation_Id
FROM
Persons P
INNER JOIN New_Persons NP
ON P.Citizen_Id = NP.Citizen_Id
AND P.Person_Full_Name = NP.Person_Full_Name
AND P.Person_Email = NP.Person_Email
AND P.Person_Assistant_Contact = NP.Person_Assistant_Contact;
差不多完成了
很好,我们有新的表格,我们想要的数据,只是他们的名字令人困惑:)
重命名表格,我们完成了:
RENAME TABLE
Persons TO Old_Persons,
New_Persons TO Persons
<强>图片的标题说明强>
Citizen_Id
中是唯一的,但您正在插入重复项。架构或插入的数据都是错误的。Old_Persons
!)New_Persons
表中的任何列可以为空,则应修改最后一个连接。您必须处理NULL
'值'个人信息
我更喜欢创建具有所需结构和约束的全新表,并使用INSERT INTO ... SELECT语句填充它们。填充新表(并验证数据)后,重命名旧表,然后重命名新表。最后一步是将索引添加到新表中。一切正常后,旧表可以存档。
我希望,这有帮助。快乐的编码:)
哦,还有SQL Fiddle demo