Как я могу обновить строки наугад?

Я хотел бы пройти таблицу и случайным образом вытереть некоторые данные. Я делаю некоторую рандомизацию данных, превращая реальные имена в поддельные и т.д. Хорошо одна из включенных таблиц имеет столбец, который составляет пустые приблизительно 40% времени. Мое имя randomizer приложение могло сделать бросок монеты где-нибудь в нем, когда это присваивает новые имена. Но я предпочел бы просто делать это в конце: случайным образом сократите некоторые данные.

У меня есть этот код, который не работает, но верные взгляды как он должны мне:

Use MyDb
go 

CREATE VIEW vRandNumber 
AS 
SELECT RAND() as RandNumber 

go  

CREATE FUNCTION RandNumber() 
RETURNS float 
AS 
  BEGIN 
  RETURN (SELECT RandNumber FROM vRandNumber) 
  END 

go  

select dbo.RandNumber()

update names set nickname = null 
where ((select dbo.RandNumber()) > 0.5)

Когда я выполняю функцию RandNumber, она прекрасна, много случайное. Но когда я делаю обновление, оно обновляет все строки половина времени и ни одной из строк другая половина времени.

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

Действительно ли это возможно без цикла и без консольного приложения?

Править: Я также попробовал его несколькими изменениями РЭНДА () в, где непосредственно и получил те же результаты.

12
задан Luke Girvin 11 February 2019 в 13:56
поделиться

6 ответов

Предполагая, что в вашей таблице имен есть поле первичного ключа с именем Id, это приведет к аннулированию псевдоним в 50% случайных строк:

update dbo.Names set Nickname = null where Id in
(
    select top 50 percent id from dbo.Names order by NEWID()
)
27
ответ дан 2 December 2019 в 04:53
поделиться

RAND () (и GetDate / CURRENT_TIMESTAMP) оценивается один раз для каждого оператора. Вам нужно как-то обойти это. Один из способов (если у вас есть удобное целое число со строкой, например столбец идентификатора) - вместо этого вызвать RAND (ID).

0
ответ дан 2 December 2019 в 04:53
поделиться

RandNumber - это функция. Функции в SQL должны каждый раз выводить один и тот же результат для одного и того же ввода, если только данные базовой базы данных не изменились. Это математическое определение функции (в отличие от того, как нормальный язык программирования обрабатывает «функцию», которая больше похожа на функционально-подобную конструкцию).

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

Возможно, вам удастся просто сослаться на RAND непосредственно в вашем запросе, но если это все равно не сработает, вам придется делать это итеративно в хранимой процедуре.

1
ответ дан 2 December 2019 в 04:53
поделиться

RAND() сохраняется в запросе.

SELECT  RAND()
FROM    names

даст вам набор одинаковых чисел.

Вам нужно сделать что-то вроде этого:

WITH    q AS
        (
        SELECT  *,
                ABS(CHECKSUM(NEWID())) % 2 AS r
        FROM    names
        )
UPDATE  q
SET     nickname = NULL
WHERE   r = 0
1
ответ дан 2 December 2019 в 04:53
поделиться

Как насчет

update names set nickname = null
where  abs(checksum(nickname) % 2) = 0
0
ответ дан 2 December 2019 в 04:53
поделиться

попробуйте что-нибудь вроде этого:

WHERE DATEPART(ms,CreateDate)>500

где «CreateDate» - это уже имеющийся в таблице столбец, в котором есть фактическая дата и время. Миллисекунда должна быть случайной

РЕДАКТИРОВАТЬ вот другой подход:

DECLARE @YourTable table (RowID int, RowValue varchar(5))
INSERT INTO @YourTable VALUES (1,'one')
INSERT INTO @YourTable VALUES (2,'two')
INSERT INTO @YourTable VALUES (3,'three')

SELECT 
    RAND(row_number() over(order by RowID)+DATEPART(ms,GETDATE())),* 
    FROM @YourTable

ВЫХОД, прогон 1:

                       RowID       RowValue
---------------------- ----------- --------
0.716200609189072      1           one
0.71621924216033       2           two
0.716237875131588      3           three

(затронуты 3 строки)

ВЫХОД, прогон 2:

                       RowID       RowValue
---------------------- ----------- --------
0.727007732518828      1           one
0.727026365490086      2           two
0.727044998461344      3           three

(3 row(s) affected)
1
ответ дан 2 December 2019 в 04:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: