mysql - 删除父子关系后保留唯一记录

Avi*_*nee 6 mysql

在mysql数据库中,我有一个业务单元表,用于维护客户业务单元的层次结构.每个业务部门都可以有父母和/或孩子.

products_client_1.business_units

id  parent_id
1   
2   1
3   1
4   1
8   1
14  3
17  2
31  1
35  4
36  1
37  4
38  2
39  31
40  8
41  3
42  31
43  
44  43
Run Code Online (Sandbox Code Playgroud)

目前,我有一个customerId表,用于维护业务单位级别的customerId

contacts_client_1.buid_customer_id

global_id   customer_id bu_id   
ABC1000033  1812130     2
ABC1000033  1812130     54
ABC1000034  4049809     2
ABC1000035  5630631     2
ABC1000082  5707052     2
ABC1000082  1111116     54
ABC1000091  5813085     2
ABC1000091  5813085     54
ABC1000093  5208477     2
ABC1000115  5045891     2
ABC1000115  5045891     54
ABC1000117  6114245     2
ABC1000117  6114247     54
ABC1000117  6114247     1
ABC1000111  1234567     38
ABC1000100  9023456     43
ABC1000100  9023457     44
Run Code Online (Sandbox Code Playgroud)

展望未来,我不想在个别业务部门级别维护客户ID.对于给定的globalId,它应该是唯一的.为此,我想根据以下条件迁移现有的客户ID数据.

如果globalId只有一个BU的customerId,则按原样迁移它而不使用bu_id.

如果globalId有2个BU的customerId(它们可以是任何级别的父子),请保留父级最可用BU的customerId.

必填表contacts_client_1.customer_id

global_id   customer_id
ABC1000033  1812130
ABC1000034  4049809
ABC1000035  5630631
ABC1000082  5707052
ABC1000091  5813085
ABC1000093  5208477
ABC1000100  9023456
ABC1000111  1234567
ABC1000115  5045891
ABC1000117  6114247
Run Code Online (Sandbox Code Playgroud)

PS: globalId在不同的父母大多数BU之间没有重叠.

business_unit表位于products_client_1 schema下,buid_customer_id表位于contacts_client_1 schema下.

相同的代码应该可以为不同的客户端执行.

这是一次性迁移.

在编写查询时需要帮助.

Pau*_*gel 0

我不确定您到底要如何处理您的数据,但以下内容应该有所帮助:

global_id仅显示表中没有父级的行buid_customer_id

select child.*
from contacts_client_1.buid_customer_id child
left join products_client_1.business_units bu
  on bu.id = child.bu_id
left join contacts_client_1.buid_customer_id parent
  on  parent.global_id = child.global_id
  and parent.bu_id     = bu.parent_id
where parent.global_id is null
Run Code Online (Sandbox Code Playgroud)

例子:

  • (ABC1000100 9023456 43)- bu_id(43) 在 中没有父级buid_customer_id,因此第一个 LEFT JOIN 不会匹配,第二个也不会匹配。由于左连接表中的所有列都将为 NULL,因此parent.global_id is null为 TRUE 并且将选择该行。
  • (ABC1000100 9023457 44)- bu_id(44) 有一个parent_id(43),因此第一个 JOIN 将找到匹配项。global_id第二个 JOIN 也会找到匹配项,因为表中存在与父 BU 相同的行buid_customer_id。因此parent.global_id不为 NULL,并且不会选择该行。
  • (ABC1000033 1812130 2)- bu_id(2) 有一个parent_id(1)。第一个 JOIN 将找到匹配项。buid_customer_id但是表中没有bu_id = 1和的行global_id = ABC1000033,因此第二个 JOIN 没有匹配项。因此parent.global_id将为 NULL 并且该行将被选择。

现在您可以使用此语句将数据复制(迁移)到新表

insert into new_table
    select child.*
    [..]
Run Code Online (Sandbox Code Playgroud)

你也可以走另一条路。如果将 LEFT JOIN 替换为 INNER JOIN 并删除 WHERE 子句,您将得到相反的结果(第一个查询未返回的所有行)。您可以使用它从表中删除所有这些行。

删除具有相同父行的所有行global_id

delete child
from contacts_client_1.buid_customer_id child
join products_client_1.business_units bu
  on bu.id = child.bu_id
join contacts_client_1.buid_customer_id parent
  on  parent.global_id = child.global_id
  and parent.bu_id     = bu.parent_id
Run Code Online (Sandbox Code Playgroud)

现在该表buid_customer_id将包含第一个查询选择的相同行。如果此数据需要位于另一个表中 - 只需重命名即可。然后你可以复制global_idcustomer_id使用

insert into customer_id (global_id, customer_id)
    select global_id, customer_id
    from new_table
Run Code Online (Sandbox Code Playgroud)