TSQL Select의 각 행에 대해 난수를 어떻게 생성합니까?
내 테이블의 각 행마다 다른 임의의 숫자가 필요합니다. 다음의 명백한 코드는 각 행에 대해 동일한 임의의 값을 사용합니다.
SELECT table_name, RAND() magic_number
FROM information_schema.tables
이 중 INT 또는 FLOAT를 얻고 싶습니다. 이야기의 나머지 부분은이 난수를 사용하여 알려진 날짜에서 임의의 날짜 오프셋을 생성합니다 (예 : 시작 날짜에서 1-14 일 오프셋).
Microsoft SQL Server 2000 용입니다.
SQL Server-Set based random numbers 를 살펴보십시오 . 자세한 설명이 나와 있습니다.
요약하면 다음 코드는 정규화 된 분포를 사용하여 0에서 13 사이의 난수를 생성합니다.
ABS(CHECKSUM(NewId())) % 14
범위를 변경하려면 식 끝에 숫자를 변경하십시오. 양수와 음수를 모두 포함하는 범위가 필요한 경우 특히주의하십시오. 잘못하면 숫자 0을 두 번 계산할 수 있습니다.
방의 수학 너트에 대한 작은 경고 :이 코드에는 약간의 편견이 있습니다. CHECKSUM()
sql Int 데이터 유형의 전체 범위에서 균일하거나 최소한 (편집자) 테스트에서 볼 수있는 정도의 숫자가됩니다. 그러나 CHECKSUM ()이 해당 범위의 맨 끝에 숫자를 생성 할 때 약간의 편차가 있습니다. 가능한 최대 정수와 원하는 최대 크기 (이 경우 14)의 크기의 마지막 정확한 배수 사이의 숫자를 얻을 때마다 그 결과는 범위의 나머지 부분보다 선호됩니다. 마지막 배수는 14의 배수입니다.
예를 들어, Int 유형의 전체 범위가 19에 불과하다고 가정하십시오. 19는 보유 할 수있는 가장 큰 정수입니다. CHECKSUM ()의 결과가 14-19 인 경우 결과 0-5에 해당합니다. CHECKSUM ()이 생성 할 가능성이 두 배이기 때문에이 숫자는 6-13보다 많이 선호됩니다. 이것을 시각적으로 설명하는 것이 더 쉽습니다. 다음은 가상 정수 범위에 대한 가능한 전체 결과 집합입니다.
체크섬 정수 : 12 34 5678 9 10 11 12 1314 15 16 17 18 19 범위 결과 : 12 34 5678 9 10 11 12 1103 34 5
여기에서 다른 것보다 더 많은 숫자를 생성 할 수있는 기회가 더 많다는 것을 알 수 있습니다 : 편향. 고맙게도 Int 유형의 실제 범위는 훨씬 큽니다. 그래서 대부분의 경우 바이어스를 거의 감지 할 수 없습니다. 그러나 심각한 보안 코드를 위해이 작업을 수행하는 경우 알고 있어야합니다.
단일 배치에서 여러 번 호출되면 rand ()는 동일한 숫자를 반환합니다.
시드 인수로 convert ( varbinary
, newid()
)를 사용하는 것이 좋습니다 .
SELECT table_name, 1.0 + floor(14 * RAND(convert(varbinary, newid()))) magic_number
FROM information_schema.tables
newid()
동일한 배치 내에서도 호출 될 때마다 다른 값을 반환하도록 보장되므로 시드로 사용하면 rand ()가 매번 다른 값을 지정하도록 프롬프트합니다.
1에서 14 사이의 임의의 정수를 얻도록 편집되었습니다.
RAND(CHECKSUM(NEWID()))
위의 0과 1 사이의 (의사) 난수를 제외하고 생성합니다. 선택에 사용되는 경우 각 행의 시드 값이 변경되므로 각 행에 대해 새로운 난수를 생성합니다 (단, 행당 고유 한 숫자를 생성 할 수는 없습니다).
상한을 10으로 조합 한 예 (숫자 1 ~ 10 생성) :
CAST(RAND(CHECKSUM(NEWID())) * 10 as INT) + 1
Transact-SQL 설명서 :
CAST()
: https://docs.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sqlRAND()
: http://msdn.microsoft.com/en-us/library/ms177610.aspxCHECKSUM()
: http://msdn.microsoft.com/en-us/library/ms189788.aspxNEWID()
: https://docs.microsoft.com/en-us/sql/t-sql/functions/newid-transact-sql
1000에서 9999 사이의 난수 생성 :
FLOOR(RAND(CHECKSUM(NEWID()))*(9999-1000+1)+1000)
"+1"-상한값 포함 (이전 예의 경우 9999)
이전 질문에 대답했지만이 답변은 이전에 제공되지 않았으므로 검색 엔진을 통해이 결과를 찾는 사람에게 유용 할 것입니다.
SQL Server 2008 CRYPT_GEN_RANDOM(8)
에는 CryptoAPI를 사용하여 암호화 적으로 강력한 난수를 생성하는 새로운 기능이 도입되었으며 로 반환됩니다 VARBINARY(8000)
. 설명서 페이지는 다음과 같습니다. https://docs.microsoft.com/en-us/sql/t-sql/functions/crypt-gen-random-transact-sql
임의의 숫자를 얻으려면 간단히 함수를 호출하여 필요한 유형으로 캐스팅하면됩니다.
select CAST(CRYPT_GEN_RANDOM(8) AS bigint)
또는 float
-1과 +1 사이 를 얻으려면 다음과 같이 할 수 있습니다.
select CAST(CRYPT_GEN_RANDOM(8) AS bigint) % 1000000000 / 1000000000.0
Rand () 함수는 테이블 SELECT 쿼리에 사용되는 경우 동일한 난수를 생성합니다. Rand 함수에 시드를 사용하는 경우에도 동일하게 적용됩니다. 다른 방법은 다음을 사용하는 것입니다.
SELECT ABS(CAST(CAST(NEWID() AS VARBINARY) AS INT)) AS [RandomNumber]
여기 에서 정보를 얻었습니다 . 문제를 잘 설명합니다.
RAND 함수에 시드로 전달할 수있는 각 행에 정수 값이 있습니까?
1과 14 사이의 정수를 얻으려면 이것이 효과가 있다고 생각합니다.
FLOOR( RAND(<yourseed>) * 14) + 1
시드가 매번 "동일한"임의의 데이터를 생성하도록 시드를 보존해야하는 경우 다음을 수행 할 수 있습니다.
1. select rand ()를 리턴하는 뷰를 작성하십시오.
if object_id('cr_sample_randView') is not null
begin
drop view cr_sample_randView
end
go
create view cr_sample_randView
as
select rand() as random_number
go
2.보기에서 값을 선택하는 UDF를 작성하십시오.
if object_id('cr_sample_fnPerRowRand') is not null
begin
drop function cr_sample_fnPerRowRand
end
go
create function cr_sample_fnPerRowRand()
returns float
as
begin
declare @returnValue float
select @returnValue = random_number from cr_sample_randView
return @returnValue
end
go
3. 데이터를 선택하기 전에 rand () 함수를 시드 한 후 select 문에서 UDF를 사용하십시오.
select rand(200); -- see the rand() function
with cte(id) as
(select row_number() over(order by object_id) from sys.all_objects)
select
id,
dbo.cr_sample_fnPerRowRand()
from cte
where id <= 1000 -- limit the results to 1000 random numbers
RAND (seedInt)에서 시드 값을 사용해보십시오. RAND ()는 명령문 당 한 번만 실행되므로 매번 같은 숫자가 표시됩니다.
정수가 아닌 임의의 고유 식별자 인 경우 사용할 수 있습니다 newid()
SELECT table_name, newid() magic_number
FROM information_schema.tables
각 행마다 RAND ()를 호출해야합니다. 여기 좋은 예가 있습니다
select round(rand(checksum(newid()))*(10)+20,2)
여기서 난수는 20에서 30 사이 round
입니다. 소수점 이하 두 자리를 최대 값으로 지정합니다.
음수를 원하면 함께 할 수 있습니다.
select round(rand(checksum(newid()))*(10)-60,2)
그러면 최소값은 -60이되고 최대 값은 -50이됩니다.
newid ()를 선택하십시오
아니면이 선택 binary_checksum (newid ())
내가 선택한 "답변"에서 때때로 문제는 분포가 항상 고르지 않다는 것입니다. 많은 행 사이에 임의의 1-14 분포가 매우 균일 해야하는 경우 이와 같은 작업을 수행 할 수 있습니다 (데이터베이스에 511 개의 테이블이 있으므로 작동합니다. 임의의 수 범위보다 행이 적을 경우 작동하지 않습니다. 잘):
SELECT table_name, ntile(14) over(order by newId()) randomNumber
FROM information_schema.tables
이런 종류의 숫자는 숫자를 순서대로 유지하고 다른 열을 무작위 화한다는 점에서 일반적인 무작위 솔루션과 반대입니다.
데이터베이스에 511 개의 테이블이 있습니다 (Information_schema에서 선택한 b / c에만 해당됨). 이전 쿼리를 가져 와서 임시 테이블 #X에 넣은 다음 결과 데이터에서이 쿼리를 실행합니다.
select randomNumber, count(*) ct from #X
group by randomNumber
이 결과를 얻었고 내 임의의 숫자가 많은 행에 균등하게 분포되어 있음을 보여줍니다.
select ABS(CAST(CAST(NEWID() AS VARBINARY) AS INT)) as [Randomizer]
항상 나를 위해 일했다
다음과 같이 쉽습니다.
DECLARE @rv FLOAT;
SELECT @rv = rand();
그리고 이것은 0-99 사이의 임의의 숫자를 테이블에 넣습니다.
CREATE TABLE R
(
Number int
)
DECLARE @rv FLOAT;
SELECT @rv = rand();
INSERT INTO dbo.R
(Number)
values((@rv * 100));
SELECT * FROM R
DROP VIEW IF EXISTS vwGetNewNumber;
GO
Create View vwGetNewNumber
as
Select CAST(RAND(CHECKSUM(NEWID())) * 62 as INT) + 1 as NextID,
'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'as alpha_num;
---------------CTDE_GENERATE_PUBLIC_KEY -----------------
DROP FUNCTION IF EXISTS CTDE_GENERATE_PUBLIC_KEY;
GO
create function CTDE_GENERATE_PUBLIC_KEY()
RETURNS NVARCHAR(32)
AS
BEGIN
DECLARE @private_key NVARCHAR(32);
set @private_key = dbo.CTDE_GENERATE_32_BIT_KEY();
return @private_key;
END;
go
---------------CTDE_GENERATE_32_BIT_KEY -----------------
DROP FUNCTION IF EXISTS CTDE_GENERATE_32_BIT_KEY;
GO
CREATE function CTDE_GENERATE_32_BIT_KEY()
RETURNS NVARCHAR(32)
AS
BEGIN
DECLARE @public_key NVARCHAR(32);
DECLARE @alpha_num NVARCHAR(62);
DECLARE @start_index INT = 0;
DECLARE @i INT = 0;
select top 1 @alpha_num = alpha_num from vwGetNewNumber;
WHILE @i < 32
BEGIN
select top 1 @start_index = NextID from vwGetNewNumber;
set @public_key = concat (substring(@alpha_num,@start_index,1),@public_key);
set @i = @i + 1;
END;
return @public_key;
END;
select dbo.CTDE_GENERATE_PUBLIC_KEY() public_key;
my_table 세트 my_field = CEILING ((RAND (CAST (NEWID () AS varbinary)) * 10)) 업데이트
1에서 10 사이의 숫자입니다.
'Programing' 카테고리의 다른 글
ggplot2를 사용한 단계별 플롯 (0) | 2020.03.12 |
---|---|
Java를 MySQL 데이터베이스에 연결 (0) | 2020.03.12 |
내림차순으로 파이썬리스트 정렬 (0) | 2020.03.12 |
JavaScript는 HTML 양식 요소에 중점을 둡니다. (0) | 2020.03.12 |
요소에 동일한 너비를 제공하지 않는 Flexbox (0) | 2020.03.12 |