SQL에서 난수로 열을 어떻게 채울 수 있습니까? 모든 행에서 동일한 값을 얻습니다.
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'");
}
'Nice programing' 카테고리의 다른 글
document.createElement ( "script") 동기식 (0) | 2020.10.28 |
---|---|
CodeIgniter-한 행만 반환합니까? (0) | 2020.10.28 |
콘텐츠 유형 text / xml; (0) | 2020.10.28 |
C ++의 클래스 선언 내에서 const 멤버 초기화 (0) | 2020.10.28 |
DOM을 사용하여 기존 SVG에 SVG 요소 추가 (0) | 2020.10.28 |