我有一个包含三个字段的表:ID,Value,Count
ID和价值构成了PK。
给定一个ID,我想选择一个由Count加权的值,然后将计数减一。
所以,如果我有
1 A 2
1 B 3
我应该有2/5的机会获得A和3/5获得B的机会。 如果选择A,则表格在
之后应如下所示1 A 1
1 B 3
下次A将有1/4的机会被选中而B将有3/4
想法?
谢谢!
更新
重量就像放在包里的那个价值的筹码数量。然后随机选择一个。
答案 0 :(得分:4)
CREATE TABLE #Vals
(
ID INT,
Value CHAR(1),
[Count] INT,
PRIMARY KEY(ID,Value)
)
INSERT INTO #Vals
SELECT 1,'A',2 UNION ALL
SELECT 1,'B',3
;WITH Nums AS
(
SELECT number
FROM master..spt_values
WHERE number>0 AND type='P'
), Row AS
(
SELECT TOP 1 v.*
FROM #Vals v
JOIN Nums n ON n.number <= v.[Count]
WHERE v.ID=1
ORDER BY CHECKSUM(NEWID())
)
UPDATE Row
SET [Count] = [Count] -1
OUTPUT inserted.*
DROP TABLE #Vals
答案 1 :(得分:1)
在MySQL中(也许有人可以把它翻译成MSSQL UPDATE语句?)这会给你需要减少的行:
SELECT *
FROM t
WHERE ID = 1
AND (
SELECT COALESCE(SUM(Count), 0)
FROM t i
WHERE ID = 1
AND i.Value < t.Value
) <= (
SELECT FLOOR(SUM(Count) * RAND())
FROM t
)
ORDER BY Value DESC
LIMIT 1
因为它是O(n²),但对于大型数据集来说它会很慢。
答案 2 :(得分:0)
试试这个(前提是此表中没有太多记录)。我做了这样的结构:
id value weight ----------- -------------------------------------------------- ----------- 1 A 2 1 B 3
然后运行以下代码。请记住,经过一段时间后,您的所有体重都将变为零,此时您将没有返回值。另外,我假设如果没有基于随机回报的权重匹配,则返回最大权重值。如果那不是您想要的,只需取出最后一次空检查
declare @weight_sum int
declare @rand_weight_value int
declare @selected_value varchar(10)
declare @id int
declare @weight int
select @weight_sum = SUM(weight) from table1 where id = 1
select @rand_weight_value = ROUND(((@weight_sum - 1) * RAND() + 1), 0)
print @rand_weight_value
declare getEm cursor local for select ID, [value], [weight] from table1 where id = 1 and [weight] > 0 order by [weight]
open getEm
while (1=1)
begin
fetch next from getEm into @id, @selected_value, @weight
if (@@fetch_status 0)
begin
DEALLOCATE getEm
break
end
if(@weight >= @rand_weight_value)
begin
update table1 set [weight] = [weight] - 1 where ID = @id and [value] = @selected_value
DEALLOCATE getEm
break
end
end
-- if no match on the weight value
if(@selected_value is null)
begin
select @id = id, @selected_value = [value] from table1 where [weight] > 0 and id = 1 order by weight desc
update table1 set weight = weight - 1 where id = @id
end
select @selected_value