使用随机字段

时间:2015-05-27 14:07:18

标签: sql sql-server sql-server-2008

我正在研究"数据混淆器"脚本。我想用假数据更新表中的每条记录。我有一个包含位置的表,并尝试从该表中选择一个随机记录来更新我的人员表中的记录。所以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

1 个答案:

答案 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,则所有行都会获得相同的值。