У меня есть следующие MySQL таблицы:
CREATE TABLE notification
(`id` int, `person_id` int, `rule_id` int, `account_id` int, `account_display_name` varchar(16))
;
INSERT INTO notification
(`id`, `person_id`, `rule_id`, `account_id`, `account_display_name`)
VALUES
(1, 1, 1, 1, 'Muad''Dib'),
(2, 1, 1, 2, 'Kwisatz Haderach'),
(3, 1, 2, 2, 'Kwisatz Haderach'),
(4, 2, 1, 3, 'Duncan'),
(5, 2, 2, 4, 'Duncan Idaho')
;
CREATE TABLE person
(`id` int, `name` varchar(6), `organization_id` int)
;
INSERT INTO person
(`id`, `name`, `organization_id`)
VALUES
(1, 'paul', 1),
(2, 'duncan', 1),
(3, 'paul', 2),
(4, 'duncan', 2),
(5, 'paul', 3),
(6, 'duncan', 3)
;
CREATE TABLE account
(`id` int, `display_name` varchar(16), `person_id` int)
;
INSERT INTO account
(`id`, `display_name`, `person_id`)
VALUES
(1, 'Muad''Dib', 1),
(2, 'Kwisatz Haderach', 1),
(3, 'Duncan', 2),
(4, 'Duncan Idaho', 2),
(5, 'Muad''Dib', 3),
(6, 'Kwisatz Haderach', 3),
(7, 'Duncan', 4),
(8, 'Duncan Idaho', 4),
(9, 'Muad''Dib', 5),
(10, 'Kwisatz Haderach', 5),
(11, 'Duncan', 6),
(12, 'Duncan Idaho', 6)
;
CREATE TABLE organization
(`id` int, `name` varchar(17))
;
INSERT INTO organization
(`id`, `name`)
VALUES
(1, 'atreides'),
(2, 'atreides_dev'),
(3, 'atreides_research')
;
CREATE TABLE rule
(`id` int, `name` varchar(14))
;
INSERT INTO rule
(`id`, `name`)
VALUES
(1, 'bug'),
(2, 'false_positive')
;
Концептуально, рассматриваемая система генерирует notification
, когда происходит событие, которое считается относящимся к person
. Будет ли генерироваться notification
, определяется rule
(отношение между person
и rule
определено в другом месте, но это выходит за рамки этого вопроса). Каждый notification
, который генерируется для person
, конкретно связан с account
, принадлежащим этому person
, и он также содержит (денормализованный) account_display_name
account
.
Обратите внимание, что person
также относится только к одному organization
.
. В настоящее время у меня есть набор notifications
(с соответствующими accounts
) для нескольких persons
в конкретном organization
, Но мне нужно переместить эти notifications
в другую реплику organizations
(с репликами persons
и accounts
) на основе rule
, вызвавшего notification
.
Ниже приведен пример тип миграции, который я пытаюсь выполнить.
состояние связанных таблиц
person
+----+--------+-----------------+
| id | name | organization_id |
+----+--------+-----------------+
| 1 | paul | 1 |
| 2 | duncan | 1 |
| 3 | paul | 2 |
| 4 | duncan | 2 |
| 5 | paul | 3 |
| 6 | duncan | 3 |
+----+--------+-----------------+
organization
+----+-------------------+
| id | name |
+----+-------------------+
| 1 | atreides |
| 2 | atreides_dev |
| 3 | atreides_research |
+----+-------------------+
account
+----+------------------+-----------+
| id | display_name | person_id |
+----+------------------+-----------+
| 1 | Muad'Dib | 1 |
| 2 | Kwisatz Haderach | 1 |
| 3 | Duncan | 2 |
| 4 | Duncan Idaho | 2 |
| 5 | Muad'Dib | 3 |
| 6 | Kwisatz Haderach | 3 |
| 7 | Duncan | 4 |
| 8 | Duncan Idaho | 4 |
| 9 | Muad'Dib | 5 |
| 10 | Kwisatz Haderach | 5 |
| 11 | Duncan | 6 |
| 12 | Duncan Idaho | 6 |
+----+------------------+-----------+
rule
+----+----------------+
| id | name |
+----+----------------+
| 1 | bug |
| 2 | false_positive |
+----+----------------+
начальное состояние уведомлений
+----+-----------+---------+------------+----------------------+
| id | person_id | rule_id | account_id | account_display_name |
+----+-----------+---------+------------+----------------------+
| 1 | 1 | 1 | 1 | Muad'Dib |
| 2 | 1 | 1 | 2 | Kwisatz Haderach |
| 3 | 1 | 2 | 2 | Kwisatz Haderach |
| 4 | 2 | 1 | 3 | Duncan |
| 5 | 2 | 2 | 4 | Duncan Idaho |
+----+-----------+---------+------------+----------------------+
Конечное состояние уведомлений
+----+-----------+---------+------------+----------------------+
| id | person_id | rule_id | account_id | account_display_name |
+----+-----------+---------+------------+----------------------+
| 1 | 3 | 1 | 5 | Muad'Dib |
| 2 | 3 | 1 | 6 | Kwisatz Haderach |
| 3 | 5 | 2 | 10 | Kwisatz Haderach |
| 4 | 4 | 1 | 7 | Duncan |
| 5 | 6 | 2 | 12 | Duncan Idaho |
+----+-----------+---------+------------+----------------------+
Как видите, person_id
и account_id
notifications
были обновлены на основе notification's
rule_id
. В частности:
- Каждый
notification
, созданный bug
rule
(ID 1), был перемещен в соответствующие реплики person
и account
в atreides_dev
organization
( ID 2). - Каждый
notification
, созданный false_positive
rule
(ID 2), был перемещен в соответствующие реплики person
и account
в atreides_research
organization
(ID 3).
Я написал SQL запрос, который (я считаю) выбирает правильные notification.person_id
и notification.account_id
на основе notification.rule_id
, но я не уверен в лучшем способ использовать это в операторе UPDATE, чтобы каждый notification
обновлялся правильно.
Вот SELECT:
select p_replica.id, acc_replica.id as account_id
from (select p.name, person_id, rule_id, account_id, account_display_name from notification n
inner join person p
on n.person_id = p.id
where p.organization_id = 1
and n.rule_id in (1)) as notifications
inner join person p_replica
on p_replica.name = notifications.name
and p_replica.organization_id = 2
inner join account acc_replica
on acc_replica.person_id = p_replica.id
and acc_replica.display_name = notifications.account_display_name;
Обратите внимание, что SELECT указывает источник organization
( ID 1), пункт назначения organization
(ID 2) и rule
, чей notifications
необходимо перенести. Напомним, что это основано на сопоставлении rule
с пунктом назначения organization
. Другими словами, для выбора всех обновленных notifications
потребуется одно выполнение этого запроса на отображение rule
-> organization
.
Как будет выглядеть запрос UPDATE для выполнения этой миграции?
Вот SQL Fiddle , с которым можно поиграть.