假设我具有以下表格格式,如何在Microsoft SQL Server中使用函数/存储过程基于随机用户的百分比来选择一个随机用户。
请注意,它应该是可满足该行中任何随机数据的通用函数。
对于普通的javascript操作等,我可以为此找到库,但是在SQL Server中找不到内置的存储过程/函数。
user percentage
-----------------
a 0.1
b 0.3
c 0.4
d 0.2
答案 0 :(得分:3)
找到每个用户的每个概率区间,然后使用RAND()
查找加权加权选择。
DECLARE @Random FLOAT = RAND()
;WITH Odds AS
(
SELECT
V.*
FROM
(VALUES
('A', 0.1),
('B', 0.3),
('C', 0.4),
('D', 0.2)
) V (UserCode, Percentage)
),
OddIntervals AS
(
SELECT
O.*,
OddStart = SUM(O.Percentage) OVER (ORDER BY O.UserCode) - O.Percentage,
OddsEnd = SUM(O.Percentage) OVER (ORDER BY O.UserCode)
FROM
Odds AS O
)
SELECT
O.*
FROM
OddIntervals AS O
WHERE
@Random > O.OddStart AND
@Random <= O.OddsEnd
OddsIntervals
如下所示:
UserCode Percentage OddStart OddsEnd
A 0.1 0.0 0.1
B 0.3 0.1 0.4
C 0.4 0.4 0.8
D 0.2 0.8 1.0
RAND()不返回1,因此最后一个间隔可能会有些不利。
如果您需要多次执行此操作,则可以使用以下脚本生成N个数量的随机数(花费4秒为我生成100k值)。您必须在每行上提供不同的种子才能获得不同的RAND()
结果,因此我使用NEWID()
作为种子。您只需将#Odds表替换为您的表即可执行。
DECLARE @AmountRandomValues INT = 100000
IF OBJECT_ID('tempdb..#RandomValues') IS NOT NULL
DROP TABLE #RandomValues
SELECT TOP (@AmountRandomValues)
RandomValue = RAND(CONVERT(VARBINARY, NEWID()))
INTO
#RandomValues
FROM
sys.columns AS s1
CROSS JOIN sys.columns AS s2
IF OBJECT_ID('tempdb..#Odds') IS NOT NULL
DROP TABLE #Odds
CREATE TABLE #Odds (
UserCode CHAR(1),
Percentage DECIMAL(3,2))
INSERT INTO #Odds (
UserCode,
Percentage)
VALUES
('A', 0.1),
('B', 0.3),
('C', 0.4),
('D', 0.2)
;WITH OddIntervals AS
(
SELECT
O.*,
OddStart = SUM(O.Percentage) OVER (ORDER BY O.UserCode) - O.Percentage,
OddsEnd = SUM(O.Percentage) OVER (ORDER BY O.UserCode)
FROM
#Odds AS O
)
SELECT
R.RandomValue,
O.*
FROM
#RandomValues AS R
INNER JOIN OddIntervals AS O ON
R.RandomValue > O.OddStart AND
R.RandomValue <= O.OddsEnd
对于100k值,以下示例的几次运行用户选择量如下:
首次运行:
UserCode Amount
A 10222
B 29883
C 39738
D 20157
第二次运行:
UserCode Amount
A 10064
B 29794
C 40061
D 20081
第三次运行:
UserCode Amount
A 10030
B 29960
C 40261
D 19749
您可以看到这与他们的赔率非常一致。