SELECT 1 + RAND(checksum(NEWID()))
SELECT 1 + ABS(checksum(NEWID())) % 28
CREATE TYPE Distribution AS TABLE (EventID INT, EventProb FLOAT, CumProb FLOAT) GOCREATE FUNCTION dbo.RN_MULTINOMIAL (@Multinomial Distribution READONLY, @URN FLOAT)RETURNS INT --Cannot use WITH SCHEMABINDING ASBEGIN RETURN ISNULL( ( SELECT TOP 1 EventID FROM @Multinomial WHERE @URN < CumProb ORDER BY CumProb) -- Handle unlikely case where URN = exactly 1.0 ,( SELECT MAX(EventID) FROM @Multinomial))END
DECLARE @MultinomialProbabilities Distribution;WITH Tally (n) AS ( SELECT TOP 28 ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM sys.all_columns)INSERT INTO @MultinomialProbabilitiesSELECT n ,CASE n WHEN 1 THEN .6/26. WHEN 2 THEN .3 WHEN 3 THEN .1 ELSE .6/26. END ,CASE n WHEN 1 THEN .6*1./26. WHEN 2 THEN .3+.6*1./26. WHEN 3 THEN .4+.6*1./26. ELSE .4+.6*(n-2)/26. ENDFROM TallySELECT * FROM @MultinomialProbabilities
DECLARE @TestNums INT = 1000;WITH Tally (n) AS ( SELECT TOP (@TestNums) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM sys.all_columns a CROSS JOIN sys.all_columns b)SELECT MNRN, CountOfMNRNs=COUNT(MNRN), ActualProbability=COUNT(MNRN)/(1.*@TestNums)FROM ( SELECT MNRN=dbo.RN_MULTINOMIAL(@MultinomialProbabilities, URN) FROM Tally CROSS APPLY (SELECT URN=RAND(CHECKSUM(NEWID()))) a ) aINNER JOIN @MultinomialProbabilities ON EventID=MNRNGROUP BY MNRN
SELECT MNRN=dbo.RN_MULTINOMIAL(@MultinomialProbabilities, URN)FROM (SELECT URN=RAND(CHECKSUM(NEWID()))) a