UPDATE CattleProds
SET SheepTherapy=(ROUND((RAND()* 10000),0))
WHERE SheepTherapy IS NULL
그런 다음 SELECT를 수행하면 내 임의의 숫자가 모든 행에서 동일하다는 것을 알 수 있습니다. 고유 한 난수를 생성하는 방법에 대한 아이디어가 있습니까?
답변
대신 결과의 각 행에 대해 다시 계산되는을 rand()
사용 newid()
하십시오. 일반적인 방법은 체크섬의 모듈로를 사용하는 것입니다. 주 checksum(newid())
에 -2,147,483,648 및 원인 정수 오버 플로우를 생성 할 수 있습니다 abs()
우리가 절대 값으로 변환하기 전에 검사 반환 값에 모듈을 사용할 필요가 있도록.
UPDATE CattleProds
SET SheepTherapy = abs(checksum(NewId()) % 10000)
WHERE SheepTherapy IS NULL
이것은 0에서 9999 사이의 임의의 숫자를 생성합니다.
답변
SQL Server 2008을 사용하는 경우 다음을 사용할 수도 있습니다.
CRYPT_GEN_RANDOM(2) % 10000
다소 간단 해 보입니다 ( 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으로 균등하게 나눌 수없는 일부 숫자가 약간 초과 표시된다는 것입니다. 이 문제를 해결하는 방법은 60,000이 넘는 숫자를 버리고 자신을 재귀 적으로 호출하여 대체 번호를 얻는 스칼라 UDF로 래핑하는 것입니다.
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
답변
나는 CHECKSUM을 사용하는 것을 좋아하지만 NEWID()
, 단순한 숫자를 생성하기 위해 복잡한 수학을 할 필요가 없기 때문에를 사용하는 것이 더 좋은 방법이라고 생각합니다 .
ROUND( 1000 *RAND(convert(varbinary, newid())), 0)
를 1000
제한으로 설정하려는 숫자로 바꿀 수 있으며 항상 더하기 기호를 사용하여 범위를 만들 수 있습니다. 100
와 사이의 임의의 숫자를 원한다고 가정 해 보겠습니다 200
. 다음과 같이 할 수 있습니다.
100 + ROUND( 100 *RAND(convert(varbinary, newid())), 0)
쿼리에 함께 넣으십시오.
UPDATE CattleProds
SET SheepTherapy= ROUND( 1000 *RAND(convert(varbinary, newid())), 0)
WHERE SheepTherapy IS NULL
답변
저는 각각 100,000,000 개의 행을 생성하여 RAND ()에 대해 2 개의 세트 기반 무작위 화 방법을 테스트했습니다. 필드를 평준화하기 위해 출력은 RAND ()를 모방하기 위해 0-1 사이의 부동 소수점입니다. 대부분의 코드는 인프라를 테스트하므로 여기에 알고리즘을 요약합니다.
-- 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을 사용하는 것은 10 ^ 18 숫자 집합에서 10 ^ 8 숫자를 뽑을 때 1 개의 중복을 볼 확률이 .000000001 %에 불과하기 때문에 가장 무작위였습니다. IOW 우리는 어떤 중복도 보지 말았어야했는데 이것도 없었습니다! 이 세트는 랩톱에서 생성하는 데 44 초가 걸렸습니다.
Cnt Pct
----- ----
1 100.000000 --No duplicates
SQL Server 실행 시간 : CPU 시간 = 134795ms, 경과 시간 = 39274ms.
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 자릿수 정도 덜 무작위로이 방법은 2 배나 빠르지 않았으며 1 억 개의 숫자를 생성하는 데 23 초 밖에 걸리지 않았습니다.
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 실행 시간 : CPU 시간 = 77156ms, 경과 시간 = 24613ms.
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'");
}
답변
