UPDATE CattleProds
SET SheepTherapy=(ROUND((RAND()* 10000),0))
WHERE SheepTherapy IS NULL
Если я затем сделаю SELECT, я вижу, что мое случайное число идентично в каждой строке . Есть идеи, как сгенерировать уникальные случайные числа?
sql-server
NibblyPig
источник
источник
Если вы используете SQL Server 2008, вы также можете использовать
Что кажется несколько проще (он также оценивается один раз для каждой строки как
newid
есть - показано ниже)DECLARE @foo TABLE (col1 FLOAT) INSERT INTO @foo SELECT 1 UNION SELECT 2 UPDATE @foo SET col1 = CRYPT_GEN_RANDOM(2) % 10000 SELECT * FROM @foo
Возврат (2 случайных числа, вероятно, разных )
col1 ---------------------- 9693 8573
Обдумывая необъяснимое отрицательное голосование, единственная законная причина, о которой я могу думать, заключается в том, что поскольку сгенерированное случайное число находится в диапазоне от 0 до 65535, которое не делится на 10 000 без остатка, некоторые числа будут представлены немного больше. Обойти это можно, заключив его в скалярную UDF, которая отбрасывает любое число, превышающее 60000, и рекурсивно вызывает себя, чтобы получить заменяющий номер.
CREATE FUNCTION dbo.RandomNumber() RETURNS INT AS BEGIN DECLARE @Result INT SET @Result = CRYPT_GEN_RANDOM(2) RETURN CASE WHEN @Result < 60000 OR @@NESTLEVEL = 32 THEN @Result % 10000 ELSE dbo.RandomNumber() END END
источник
Хотя мне нравится использовать КОНТРОЛЬНУЮ СУММ, я считаю, что лучше использовать
NEWID()
, просто потому, что вам не нужно выполнять сложную математику для генерации простых чисел.Вы можете заменить
1000
любое число, которое хотите установить в качестве ограничения, и вы всегда можете использовать знак плюса для создания диапазона, скажем, вам нужно случайное число между100
и200
, вы можете сделать что-то вроде:Объединяя это в свой запрос:
UPDATE CattleProds SET SheepTherapy= ROUND( 1000 *RAND(convert(varbinary, newid())), 0) WHERE SheepTherapy IS NULL
источник
Я протестировал 2 метода рандомизации на основе наборов против RAND (), сгенерировав по 100000000 строк для каждого. Для выравнивания поля вывод представляет собой число с плавающей запятой между 0-1, чтобы имитировать RAND (). Большая часть кода - это инфраструктура тестирования, поэтому я резюмирую алгоритмы здесь:
-- Try #1 used (CAST(CRYPT_GEN_RANDOM(8) AS BIGINT)%500000000000000000+500000000000000000.0)/1000000000000000000 AS Val -- Try #2 used RAND(Checksum(NewId())) -- and to have a baseline to compare output with I used RAND() -- this required executing 100000000 separate insert statements
Использование CRYPT_GEN_RANDOM было явно наиболее случайным, поскольку вероятность увидеть хотя бы 1 дубликат составляет всего 0,0000001% при извлечении 10 ^ 8 чисел ИЗ набора из 10 ^ 18 чисел. IOW мы не должны были видеть никаких дубликатов, а этого не было! На создание этого набора на моем ноутбуке ушло 44 секунды.
Cnt Pct ----- ---- 1 100.000000 --No duplicates
Время выполнения SQL Server: время ЦП = 134795 мс, затраченное время = 39274 мс.
IF OBJECT_ID('tempdb..#T0') IS NOT NULL DROP TABLE #T0; GO WITH L0 AS (SELECT c FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c)) -- 2^4 ,L1 AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B) -- 2^8 ,L2 AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B) -- 2^16 ,L3 AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B) -- 2^32 SELECT TOP 100000000 (CAST(CRYPT_GEN_RANDOM(8) AS BIGINT)%500000000000000000+500000000000000000.0)/1000000000000000000 AS Val INTO #T0 FROM L3; WITH x AS ( SELECT Val,COUNT(*) Cnt FROM #T0 GROUP BY Val ) SELECT x.Cnt,COUNT(*)/(SELECT COUNT(*)/100 FROM #T0) Pct FROM X GROUP BY x.Cnt;
Почти на 15 порядков меньше случайности, этот метод был не вдвое быстрее, всего за 23 секунды для генерации 100 миллионов чисел.
Cnt Pct ---- ---- 1 95.450254 -- only 95% unique is absolutely horrible 2 02.222167 -- If this line were the only problem I'd say DON'T USE THIS! 3 00.034582 4 00.000409 -- 409 numbers appeared 4 times 5 00.000006 -- 6 numbers actually appeared 5 times
Время выполнения SQL Server: время ЦП = 77156 мс, затраченное время = 24613 мс.
IF OBJECT_ID('tempdb..#T1') IS NOT NULL DROP TABLE #T1; GO WITH L0 AS (SELECT c FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c)) -- 2^4 ,L1 AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B) -- 2^8 ,L2 AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B) -- 2^16 ,L3 AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B) -- 2^32 SELECT TOP 100000000 RAND(Checksum(NewId())) AS Val INTO #T1 FROM L3; WITH x AS ( SELECT Val,COUNT(*) Cnt FROM #T1 GROUP BY Val ) SELECT x.Cnt,COUNT(*)*1.0/(SELECT COUNT(*)/100 FROM #T1) Pct FROM X GROUP BY x.Cnt;
Сама по себе функция RAND () бесполезна для генерации на основе наборов, поэтому генерация базовой линии для сравнения случайности заняла более 6 часов, и ее пришлось перезапускать несколько раз, чтобы наконец получить нужное количество строк вывода. Также кажется, что случайность оставляет желать лучшего, хотя это лучше, чем использование контрольной суммы (newid ()) для повторного заполнения каждой строки.
Cnt Pct ---- ---- 1 99.768020 2 00.115840 3 00.000100 -- at least there were comparitively few values returned 3 times
Из-за перезапусков не удалось зафиксировать время выполнения.
IF OBJECT_ID('tempdb..#T2') IS NOT NULL DROP TABLE #T2; GO CREATE TABLE #T2 (Val FLOAT); GO SET NOCOUNT ON; GO INSERT INTO #T2(Val) VALUES(RAND()); GO 100000000 WITH x AS ( SELECT Val,COUNT(*) Cnt FROM #T2 GROUP BY Val ) SELECT x.Cnt,COUNT(*)*1.0/(SELECT COUNT(*)/100 FROM #T2) Pct FROM X GROUP BY x.Cnt;
источник
require_once('db/connect.php'); //rand(1000000 , 9999999); $products_query = "SELECT id FROM products"; $products_result = mysqli_query($conn, $products_query); $products_row = mysqli_fetch_array($products_result); $ids_array = []; do { array_push($ids_array, $products_row['id']); } while($products_row = mysqli_fetch_array($products_result)); /* echo '<pre>'; print_r($ids_array); echo '</pre>'; */ $row_counter = count($ids_array); for ($i=0; $i < $row_counter; $i++) { $current_row = $ids_array[$i]; $rand = rand(1000000 , 9999999); mysqli_query($conn , "UPDATE products SET code='$rand' WHERE id='$current_row'"); }
источник