MySQL - 仅在共享一个公共值的两列中的一列中设置值

时间:2013-07-10 13:16:03

标签: mysql sql

我有一个contacts表,其中包含自动递增的主键id以及partner_id列上的自引用一对一关系。

我从各种来源的CSV中导入了很多联系人,其中一些联系人的表现很差,所以我不得不应用一些智能来找出谁是合作伙伴,如果他们有合作伙伴的话。

我已经进入了导入后的阶段,我在联系人表格中有行,而我确定为合作伙伴的任何对都在import_group列中共享该对唯一的值。

我现在不得不写一个查询来执行以下操作:

如果两行在import_group中共享相同的值,请将两行中第一行的partner_id设置为两行中第二行的id,但不要设置第一行的partner_id到第一行的id。由于引用此数据库的应用程序的设计,此结构是必需的。

这将在一个包含最多约4,000,000行的表上运行,在系统管理员运行的手动导入期间每月少于一次,因此效率不是此查询的特定目标。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

使用自联接,如果按id排序,则可以使用WHERE子句确保只获得每对中的一个。例如,

UPDATE contacts as c1
    JOIN contacts as c2
        ON c2.import_group = c1.import_group
    SET c1.partner_id = c2.id
WHERE c1.id < c2.id;

我无法访问sql小提琴,所以这是我测试它的方式:

create table contacts (id int, import_group int, partner_id int);
insert into contacts values (1, NULL, NULL), (2, 100, NULL), (3, 100, NULL), (4, NULL, NULL), (5, 101, NULL), (6, NULL, NULL), (7, 101, NULL);

select * from contacts;
+------+--------------+---------+
| id   | import_group | partner |
+------+--------------+---------+
|    1 |         NULL |    NULL |
|    2 |          100 |       3 |
|    3 |          100 |    NULL |
|    4 |         NULL |    NULL |
|    5 |          101 |       7 |
|    6 |         NULL |    NULL |
|    7 |          101 |    NULL |
+------+--------------+---------+
7 rows in set (0.00 sec)

答案 1 :(得分:0)

您可以通过自我加入识别所有合作伙伴。然后,您只想设置具有“较低”contact.id的那个。

以下更新会在contact上自我加入以查找合作伙伴。然后它有一个不等式,所以它保留了set的第一行:

update contacts c join
       contacts cpart
       on c.import_group = cpart.import_group and
          c.id < cpart.id
    set c.partner_id = cpart.id;

注意:这假设所有合作伙伴都是二元的。如果您有多方合作关系,那么需要更多关于数据应该是什么样的信息。