我正在研究"数据混淆器"脚本。我想用假数据更新表中的每条记录。我有一个包含位置的表,并尝试从该表中选择一个随机记录来更新我的人员表中的记录。所以SQL类似于此
UPDATE Person
SET City = (SELECT TOP 1 City
FROM z.CityStateZip c2
ORDER BY Newid())
这个问题是它只选择1个城市,而不是为每个人选择一个随机城市。我也试过了
(SELECT TOP 1 City FROM z.CityStateZip c2 ORDER BY NEWID()), PersonId, from Person
但它仍然只选择1个城市(我认为子查询每次记录都运行一次)而不是我想要的 - 每个记录的随机城市。
我也尝试过以相同的结果进行联接,只选择了一个城市......
SELECT t.City,
PersonId
FROM Person
INNER JOIN (SELECT TOP 1 City
FROM z.CityStateZip c2
ORDER BY Newid()) t
ON 1 = 1
我试图将此语句推送到函数中,但SQL Server不允许我在函数内使用NEWID()
。
答案
我修改了Giorgi的答案以及相关问题的答案并提出了这个问题,它非常快!我改变了我随机选择一个城市的方式。 NewId()的订单是一个问题。所以Person有5k记录,CityStateZip有~30K,我把它从40秒降到4 ......(现在更快没有计数子查询)
DECLARE @count bigint
SELECT @count = count(*) from z.CityStateZip
UPDATE p
SET p.City= b.City
FROM Person p
CROSS APPLY (SELECT TOP 1 City -- if Id is unique, top 1 shouldn't be necessary
FROM z.CityStateZip
WHERE p.SomeKey = p.SomeKey and -- ... the magic! ↓↓↓
Id = (Select ABS(Checksum(NewID()) % @count))) b
答案 0 :(得分:1)
您应该强制数据库引擎评估每行的新值。您可以通过在外表上添加dummy where子句来完成此操作,如:
DECLARE @city TABLE(ID INT IDENTITY(1, 1), City VARCHAR(100))
INSERT INTO @city VALUES
('Dallas'),
('New York'),
('Washington'),
('Las Vegas')
DECLARE @random TABLE(ID INT IDENTITY(1, 1), City VARCHAR(100))
INSERT INTO @random VALUES
('Manchester'),
('London'),
('Oxford'),
('Liverpool')
SELECT * FROM @city c
CROSS APPLY(SELECT TOP 1 * FROM @random r WHERE c.ID = c.ID ORDER BY NEWID()) ca
如果您删除WHERE c.ID = c.ID
,则所有行都会获得相同的值。