Обновить новый столбец внешнего ключа существующей таблицы с идентификаторами из другой таблицы на SQL сервере - PullRequest
1 голос
/ 09 июля 2020

У меня есть существующая таблица, в которую я добавил новый столбец, который должен содержать идентификатор записи в другой (новой) таблице.

Упрощенная структура выглядит примерно так:

Таблица клиентов

[CustomerId] [GroupId] [LicenceId]  <-- new column

Таблица лицензий <- новая таблица </strong>

[LicenceId] [GroupId]

Таблица лицензий содержит определенное количество лицензий на группу, чем можно назначить клиентам в той же группе. Есть несколько групп, и каждая группа имеет переменное количество клиентов и лицензий. Допустим, для группы 1 доступно 100 лицензий, а в группе 1 - 50 клиентов, поэтому каждый может получить лицензию. Клиентов никогда не бывает больше, чем лицензий.

Пример

Customer
[CustomerId] [GroupId] [LicenceId]
 1            1         NULL
 2            1         NULL
 3            1         NULL
 4            1         NULL
 5            2         NULL
 6            2         NULL
 7            2         NULL
 8            3         NULL
 9            3         NULL

Licence
[LicenceId] [GroupId]
 1            1
 2            1
 3            1
 4            1
 5            1
 6            1
 7            2
 8            2
 9            2
 10           2
 11           2
 12           3
 13           3
 14           3
 15           3
 16           3
 17           3

Desired outcome

Customer
[CustomerId] [GroupId] [LicenceId]
 1            1         1
 2            1         2
 3            1         3
 4            1         4
 5            2         7
 6            2         8
 7            2         9
 8            3         12
 9            3         13

Итак, теперь мне нужно сделать это одноразовое обновление, чтобы дать каждому клиенту лицензию, и я не знаю, как go об этом.

Мне нельзя использовать курсор. Кажется, я не могу выполнить ОБНОВЛЕНИЕ MERGE UPDATE, потому что присоединение клиента к таблице лицензий по GroupId приведет к нескольким совпадениям.

Как мне назначить каждому клиенту следующий доступный LicenceId в их группе в одном запросе? Возможно ли это вообще?

Ответы [ 2 ]

0 голосов
/ 09 июля 2020

Гордон очень хорошо выразился в своем ответе. Позвольте мне разбить его на более простые шаги.

Шаг 1. Используйте функцию ROW_NUMBER (), чтобы присвоить SeqNum клиентам. Используйте PARTITION BY GroupId, чтобы номер начинался с 1 в каждой группе. Я бы ЗАКАЖИЛ ПО CustomerId

Шаг 2. Используйте функцию ROW_NUMBER (), чтобы назначить SeqNum лицензиям. Используйте PARTITION BY GroupId, чтобы номер начинался с 1 в каждой группе. ORDER BY LicenseId, потому что ваша просьба состоит в том, чтобы «назначить каждому клиенту следующий доступный LicenceId в их группе».

Теперь используйте эти 2 запроса для обновления LicenseId в таблице Customer.

0 голосов
/ 09 июля 2020

Вы можете использовать оконные функции:

with c as (
      select c.*, row_number() over (partition by groupid order by newid()) as seqnum
      from customers c
     ), 
     l as (
      select l.*, row_number() over (partition by groupid order by newid()) as seqnum
      from licenses c
     )
update c
    set c.licenceid = l.licenseid
    from c join
         l
         on c.seqnum = l.seqnum and c.groupid = l.groupid;

При этом лицензии назначаются случайным образом . Это действительно просто для развлечения. Самый эффективный метод - использовать:

row_number() over (partition by groupid order by (select null)) as seqnum

SQL Сервер часто избегает дополнительной операции сортировки в этом случае.

Но вы можете захотеть упорядочить их по другому - для например, путем упорядочивания идентификаторов клиентов, или столбца даты, или чего-то еще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...