我有一个数据库表,其中包含由数据创建工具创建的随机个人详细信息。
我想使用此表中的值来更新另一个表中的字段,以便在我们对另一台服务器上的问题进行故障排除时屏蔽实时个人详细信息。
表格如下:
表 1:tblRandom_Data
字段: First_Name |姓
表 2:客户
字段: 客户 ID [GUID] |First_Name |姓氏 |Address_Line1...
我想通过从 tblCustomers 中选择一个随机First_Name值来更新 tblCustomers 中所有行的First_Name字段tblRandom_Data。
我已经尝试了以下内容,但这会更新所有选择相同随机名字的行。所有值不需要是唯一的,但需要有一些差异。
Update tblCustomers
SET First_Name = (SELECT TOP 1 First_Name
FROM tblRandom_Data
ORDER BY NEWID()
)
您可以使用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;
问题是SQL Server"优化"查询以仅运行一次子查询。
我发现最简单的解决方案是相关子句——即使该子句毫无意义。 假设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;
这也具有"平衡"名称的好处。 因此,如果客户数多于其他表中的行数,则分配名称的次数大致相同。
以下是使用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
的组中的每条记录影响随机数。外部查询执行实际更新。
DB Fiddlde 上的演示
示例数据:
select * from tblCustomers;
customer_id | first_name | 姓氏 ----------: |:--------- |:------ 1 |空|零2 |空|零3 |空|零4 |空|零
select * from tblRandom_Data;
first_name | 姓氏 :--------- |:------ 福 |酒吧 巴兹 |动物园
运行更新后:
select * from tblCustomers;
customer_id | first_name | 姓氏 ----------: |:--------- |:------ 1 |巴兹 |动物园 2 |福 |酒吧 3 |巴兹 |动物园 4 |福 |酒吧