SQL обновить поле из другой таблицы, выбрав значение на основе строки таблицы - PullRequest
0 голосов
/ 06 января 2020

У меня есть таблица базы данных, которая содержит случайные личные данные, созданные инструментом создания данных.

Я хочу использовать значения из этой таблицы, чтобы обновить поля в другой таблице, чтобы замаскировать действительные личные данные при устранении неполадок на другом сервере.

Таблицы будут выглядеть следующим образом:


Таблица 1: tblRandom_Data

Поля: First_Name | Фамилия


Таблица 2: tblCustomers

Поля: CustomerID [GUID] | First_Name | Фамилия | Address_Line1 ..........


Я хочу обновить поле First_Name во всех строках tblCustomers, выбрав случайное значение First_Name из tblRandom_Data.

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

Update tblCustomers 
        SET First_Name = (SELECT TOP 1 First_Name 
                          FROM tblRandom_Data
                          ORDER BY NEWID()
                         )

Ответы [ 3 ]

1 голос
/ 06 января 2020

Вы можете использовать apply:

select c.*, rd.first_name
from tblCustomers c cross apply
     ( select top (1) rd.first_name
       from tblRandom_Data rd
       where rd.address_line1 <> c.first_name -- you can use any column combination that would always be not matched with each other
       order by newid()
     ) rd;
1 голос
/ 06 января 2020

Проблема в том, что SQL Сервер "оптимизирует" запрос, чтобы выполнить подзапрос только один раз.

Я считаю, что самым простым решением является предложение корреляции - даже если это предложение не имеет смысла. Предполагая, что tblCustomers.First_Name никогда не является NULL:

UPDATE c 
    SET First_Name = (SELECT TOP 1 First_Name 
                      FROM tblRandom_Data rd
                      WHERE rd.First_Name <> c.First_Name
                      ORDER BY NEWID()
                     )
FROM tblCustomers c;

Другой метод заключается в "циклическом просмотре" значений:

UPDATE c
    SET First_Name = rd.First_Name
    FROM (SELECT c.*,
                 ROW_NUMBER() OVER (ORDER BY NEWID()) as seqnum
          FROM tblCustomers c
         ) c JOIN
         (SELECT rd.*,
                 ROW_NUMBER() OVER (ORDER BY NEWID()) as seqnum,
                 COUNT(*) OVER () as cnt
          FROM tblRandom_Data rd
         ) rd
         ON (c.seqnum % rd.cnt) = rd.seqnum - 1;

Это также имеет преимущество "балансировки" имена. Поэтому, если в другой таблице больше клиентов, чем строк, имена будут назначаться примерно одинаковое количество раз.

0 голосов
/ 06 января 2020

Вот один из способов сделать это с помощью row_number() и обновляемого cte:

with cte as (
    select 
        c.first_name, 
        c.surname, 
        r.first_name r_first_name, 
        r.surname r_surname,
        row_number() over(partition by c.customer_id order by newid()) rn
    from tblCustomers c
    cross join tblRandom_Data r 
)
update cte 
set first_name = r_first_name, surname = r_surname
where rn = 1

Cte генерирует декартово произведение обеих таблиц и влияет на случайное число для каждой записи в группах, имеющих одинаковые customer_id. Внешний запрос выполняет фактическое обновление.

Демонстрация по БД Fiddlde

Пример данных:

select * from tblCustomers;
customer_id | first_name | surname
----------: | :--------- | :------
          1 | <em>null</em>       | <em>null</em>   
          2 | <em>null</em>       | <em>null</em>   
          3 | <em>null</em>       | <em>null</em>   
          4 | <em>null</em>       | <em>null</em>   
select * from tblRandom_Data;
first_name | surname
:--------- | :------
foo        | bar    
baz        | zoo    

После запуска обновления:

select * from tblCustomers;
customer_id | first_name | surname
----------: | :--------- | :------
          1 | baz        | zoo    
          2 | foo        | bar    
          3 | baz        | zoo    
          4 | foo        | bar    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...