Я хотел бы пройти таблицу и случайным образом вытереть некоторые данные. Я делаю некоторую рандомизацию данных, превращая реальные имена в поддельные и т.д. Хорошо одна из включенных таблиц имеет столбец, который составляет пустые приблизительно 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 будет выполнена однажды для каждой строки в таблице. По-видимому, нет.
Действительно ли это возможно без цикла и без консольного приложения?
Править: Я также попробовал его несколькими изменениями РЭНДА () в, где непосредственно и получил те же результаты.
Предполагая, что в вашей таблице имен есть поле первичного ключа с именем Id, это приведет к аннулированию псевдоним в 50% случайных строк:
update dbo.Names set Nickname = null where Id in
(
select top 50 percent id from dbo.Names order by NEWID()
)
RAND () (и GetDate / CURRENT_TIMESTAMP) оценивается один раз для каждого оператора. Вам нужно как-то обойти это. Один из способов (если у вас есть удобное целое число со строкой, например столбец идентификатора) - вместо этого вызвать RAND (ID).
RandNumber
- это функция. Функции в SQL должны каждый раз выводить один и тот же результат для одного и того же ввода, если только данные базовой базы данных не изменились. Это математическое определение функции (в отличие от того, как нормальный язык программирования обрабатывает «функцию», которая больше похожа на функционально-подобную конструкцию).
Поскольку результат вашей функции никогда не должен изменяться во время оператора обновления (который является атомарной операцией), компилятор плана запроса для вашего запроса вызывает только RandNumber
один раз, а затем кэширует результат.
Возможно, вам удастся просто сослаться на RAND
непосредственно в вашем запросе, но если это все равно не сработает, вам придется делать это итеративно в хранимой процедуре.
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
Как насчет
update names set nickname = null
where abs(checksum(nickname) % 2) = 0
попробуйте что-нибудь вроде этого:
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)