【问题标题】:selecting random rows based on weight on another row根据另一行的权重选择随机行
【发布时间】:2013-05-23 19:50:55
【问题描述】:

我需要根据另一行的权重从表中选择随机行。就像用户输入随机值 50 一样,我需要从表中选择 50 个随机行,因为权重较高的行返回的次数更多。我看到使用 NEWID() 来选择 n 个随机行和这个链接

Random Weighted Choice in T-SQL

我们可以根据另一行的权重选择一行,但我需要根据用户随机输入数选择几行,所以最好的方法是使用上面链接中的建议答案并循环它 n 个次(但我认为它会返回同一行)还有其他简单的解决方案吗?

我的桌子是这样的

ID Name Freq
1  aaa  50
2  bbb  30
3  ccc  10

所以当用户输入 50 时,我需要返回 50 个随机名称,所以它应该比 ccc 更多 aaa、bbb。可能像 25 aaa、15 bbb 和 10 ccc。任何与此接近的东西都可以。我看到了这个答案,但是当我对我的数据库执行时,它似乎运行了 5 分钟并且还没有结果。 SQL : select one row randomly, but taking into account a weight

【问题讨论】:

  • 以下是什么意思? ...being that the rows with higher weight gets returned more number of times.
  • @AbeMiessler 在问题中添加了更多解释,谢谢
  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • @MartinSmith sql server 2012
  • 当您说“权重较高的行返回的次数更多”时,您的意思是同一行可以多次返回吗?

标签: sql-server stored-procedures


【解决方案1】:

我认为这里的困难部分是让任何单独的行可能出现不止一次。我会考虑做以下事情:

1) 建立一个临时表,根据记录的频率复制记录(我确信有更好的方法,但我想到的第一个答案是一个简单的 while 循环......这个特别的仅当频率值为整数时才有效)

create table #dup
(
    id  int,
    nm  varchar(10)
)

declare @curr int, @maxFreq int
select @curr=0, @maxFreq=max(freq)
from tbl

while @curr < @maxFreq
 begin
    insert into #dup
    select id, nm
    from tbl
    where freq > @curr

    set @curr = @curr+1
 end

2) 选择排名靠前的记录,按随机值排序

select top 10 *
from #dup
order by newID()

3) 清理

drop table #dup

【讨论】:

  • 谢谢!我认为现在我可以使用这个解决方案,唯一的问题是在 temptable 上再次随机选择不会返回最大的优化结果。如果我找到一些解决方案,希望在 c# 方面改进它
  • @Lav,“优化结果”是什么意思?如果结果是随机的,您将不会始终根据权重得到均匀分布。但是,与权重较低的行相比,权重较高的行更有可能出现在结果集中。
  • 是的,当我执行此操作时,您是对的
【解决方案2】:

也许您可以尝试以下方法:

ORDER BY Freq * rand()

在你的 sql 中?因此,理论上,具有较高 Freq 值的列应该比具有较低 Freq 值的列更频繁地返回。这似乎有点骇人听闻,但它可能会奏效!

【讨论】:

  • 我的第一个想法也是,但要求是同一行应该能够根据频率多次返回。这只会允许它返回一次。
  • 这不会选择具有更多频率的行,它只是返回随机值。频率不是该值出现在表中的次数,它只是描述该行权重的另一列。所以即使频率为 3000,该行也不会在表中出现 3000 次以被频繁选择。
  • 我不认为你可以在 mysql 中任意复制行,所以如果这是要求,mysql 不是解决方案。相反应该使用PHP。这也不会选择随机行。它选择(随机 x 频率)。由于 rand() 如果在给定 2 个随机但相等的值的情况下 freq 较低,则返回一个随机浮点数 [0...1],因此较高的 freq 获胜。这是我的意图。
  • @beiller 明白了,谢谢,但这会首先选择频率较高的行,但只选择一次。实际上这似乎有效,你可以看看它是否正确 SELECT top(100) t.*, RAND () * t.Freq AS w FROM table t ORDER BY w DESC
  • 啊我还以为是mysql/php哈哈。如果您有一小部分要复制的初始名称,请在应用程序层中进行。循环遍历列表并每次选择一个随机值。
猜你喜欢
  • 2018-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多