create function GetRandom(@min int, @max int) returns intasbegin declare @diff int = @max - @min + 1 return @min + crypt_gen_random(1) % @diffend
-- This runs for about 50s on my computer.declare @t table (Number int)declare @winners table (Number int)declare @i int = 0declare @iCount int = 10declare @j int = 0declare @jCount int = 100000while (@i < @iCount)begin delete from @t set @j = 0 while (@j < @jCount) begin insert into @t (Number) select dbo.GetRandom(1, 3) set @j += 1 end insert into @winners (Number) select top 1 Number from ( select Number, count(*) C from @t group by Number ) x order by C desc set @i += 1endselect Number, count(*)from @winnersgroup by Numberorder by count(*) desc
Number ----------- -----------1 92 1
Microsoft SQL Server 2008 R2 (SP1) - 10.50.2500.0 (X64) Jun 17 2011 00:54:03 Copyright (c) Microsoft Corporation Standard Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1) (Hypervisor)
-- Data definition and setupDECLARE @NumberOfRNs INTSELECT @NumberOfRNs = 100--CREATE TYPE Distribution AS TABLE (EventID INT, EventProb FLOAT, CumProb FLOAT) DECLARE @Binomial AS Distribution-- Simulate a coin toss with a Binomial DistributionINSERT INTO @BinomialSELECT 0, 0.5, 0.5 UNION ALL SELECT 1, 0.5, 1.0-- Create random numbers for the selected distributionsSELECT TOP (@NumberOfRNs) RandomBinomial = dbo.RN_MULTINOMIAL(@Binomial, URN)INTO #MyRandomNumbersFROM sys.all_columns a1 CROSS APPLY sys.all_columns a2CROSS APPLY (SELECT RAND(CHECKSUM(NEWID()))) URN(URN)SELECT RandomBinomial, Number=COUNT(RandomBinomial)FROM #MyRandomNumbersGROUP BY RandomBinomialDROP TABLE #MyRandomNumbers
--CREATE TYPE Distribution AS TABLE (EventID INT, EventProb FLOAT, CumProb FLOAT) DECLARE @Binomial AS DistributionDECLARE @MinNumber INT = 50, @MaxNumber INT = 500;WITH Tally AS ( SELECT n=number FROM [master].dbo.spt_values Tally WHERE [Type] = 'P' AND Number BETWEEN @MinNumber AND @MaxNumber)INSERT INTO @BinomialSELECT n, 1./(1+@MaxNumber-@MinNumber), (1.+n-@MinNumber)/(1.+@MaxNumber-@MinNumber)FROM TallySELECT *FROM @Binomial
[SqlFunction]public static int RndBetween(int minValue, int maxValue){ if (minValue > maxValue) throw new ArgumentOutOfRangeException("minValue"); if (minValue == maxValue) return minValue; // Make maxValue inclusive. maxValue++; var rng = new RNGCryptoServiceProvider(); var uint32Buffer = new byte[4]; long diff = maxValue - minValue; while (true) { rng.GetBytes(uint32Buffer); uint rand = BitConverter.ToUInt32(uint32Buffer, 0); const long max = (1 + (long)int.MaxValue); long remainder = max % diff; if (rand < max - remainder) { return (int)(minValue + (rand % diff)); } }}