【问题标题】:On insert increment value of one column of unique composite key if duplicate如果重复,则插入一列唯一复合键的增量值
【发布时间】:2016-03-09 11:59:09
【问题描述】:

我正在将数据从数据库传输到另一个数据库。原始表具有以下结构(其中key contact 是布尔值):

+------------+-----------+-------------+
| contact_id | school_id | key_contact |
+------------+-----------+-------------+
| 1          | 1         | 1           |
| 2          | 2         | 0           |
| 3          | 2         | 1           |
| 4          | 2         | 1           |
| 5          | 3         | 0           |
+------------+-----------+-------------+

我想让它变成以下形状,其中display_order 是与school_id 的复合唯一索引:

+------------+-----------+---------------+
| contact_id | school_id | display_order |
+------------+-----------+---------------+
| 1          | 1         | 1             |
| 2          | 2         | 3             |
| 3          | 2         | 1             |
| 4          | 2         | 2             |
| 5          | 3         | 1             |
+------------+-----------+---------------+

逻辑是如果key_contact = 1 那么display_order 应该为1,除非contact_id 与相同的school_id 已经有一个display_order 的值为1,那么它应该插入下一个增量可用school_id 独有的值。然后,我想插入所有联系人,其中key_contact = 0 将下一个可用的key_contact 整数分配给school_id

我为这两列创建了唯一索引:

UNIQUE KEY `contact_school_display_order_school_id_unique` (`display_order`,`school_id`)

我尝试过使用INSERT... ON DUPLICATE KEY UPDATE,但我真的想要在重复键上将插入值的值增加到school_id 唯一的下一个整数。

任何指针将不胜感激。

【问题讨论】:

  • 如果没有学校的主要联系人怎么办,例如您的示例中具有 school_id=3 的学校?
  • @PaulSpiegel where key_contact = 0 并且它是学校的唯一联系人,那么它的 display_order 应该是 1。所有联系人都应该有一个显示顺序,但关键联系人的排名应该更高(更低号码!)比同一所学校的非关键联系人。

标签: mysql


【解决方案1】:

从表 contacts1 迁移到 contacts2

insert into contacts2
    select 
        c1.contact_id,
        c1.school_id,
        count(c2.contact_id) as display_order
    from contacts1 c1
    join contacts1 c2
        on  c2.school_id = c1.school_id
        and (
            c2.key_contact > c1.key_contact
            or
            c2.key_contact = c1.key_contact and c2.contact_id <= c1.contact_id
        )
    group by c1.contact_id, c1.school_id
    order by c1.contact_id;

sqlfiddle demo

说明

关键逻辑在join条件中:

            c2.key_contact > c1.key_contact
            or
            c2.key_contact = c1.key_contact and c2.contact_id <= c1.contact_id

此条件定义与来自c1 的行相比,来自c2 的行对给定学校具有更高或相等的联系优先级。 (仅当contact_id 相同时,优先级才相等。)在SELECT 部分,我们计算来自c1 (group by c1.contact_id) 的每个contact_id 具有更高或相同优先级的所有行。

            c2.key_contact > c1.key_contact

仅当 c1.key_contact=0c2.key_contact=1 时为真。因此,此条件找到的c2 中的每一行都具有更高的优先级,并将被计算在内。

            c2.key_contact = c1.key_contact and c2.contact_id <= c1.contact_id

如果key_contact 相等,那么我们只计算小于或等于contact_id 的行。

这给您的结果与您像这样对表格进行排序一样:

select *
from contacts1 c1
order by c1.school_id, c1.key_contact desc, c1.contact_id

然后枚举每所学校的行。

【讨论】:

  • 这很漂亮。那是什么,天鹅绒?谢谢你。如果您能阐明逻辑,将不胜感激。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-07
  • 1970-01-01
相关资源
最近更新 更多