我已在此处看到此帖(http://stackoverflow.com/questions/1398113/sql-select-one-row-randomly-but-taking-into-account-a-weight),但无法解决。我在哪里放'Stuff'表?为什么他们不使用NEWID()而不是RND()?
桌上的东西
id item weight location
1 ball 1 Wyoming
2 cup 2 Alaska
3 sock 1 Idaho
4 car 3 Miami
5 hot girl 5 Brazil
现在根据上面提到的那篇文章,我应该这样做
SELECT TOP 1 t.*
FROM @Table t
INNER JOIN (SELECT t.id, sum(tt.weight) AS cum_weight
FROM @Table t
INNER JOIN @Table tt ON tt.id <= t.id
GROUP BY t.id) tc
ON tc.id = t.id,
(SELECT SUM(weight) AS total_weight FROM @Table) tt,
(SELECT RAND() AS rnd) r
WHERE r.rnd * tt.total_weight <= tc.cum_weight
ORDER BY t.id ASC
我想做上述事情,但是以这种方式:
SELECT TOP (1) from stuff WHERE blahblahblah AND (location='Brazil' OR location='Wyoming' OR location='Brazil') AND (weight <= cum_weight) ORDER BY NEWID()
我只是猜测我可以使用NEWID()而不是强迫使用RND()
答案 0 :(得分:0)
您可以通过从累积总和中取样而不是从记录中取样来完成此操作。我们的想法是获取权重的累积和,然后采用随机值到最大权重,最后查看哪个记录在该随机值周围有累积和。 SQL看起来像:
select top 1 t.*
from (select t.*, cumulative_sum(weight) as cumweight,
sum(weight) over (partition by NULL) as totalweight
from t
) t
where rand()*(totalweight+1) < cumweight
order by cumweight desc
这样做是创建累积权重,然后创建一个随机变量,直到权重的总和。选择累计权重小于总重量的最后一条记录。 “+1”只是为了确保可以选择任何记录,即使是最后一个记录。
在SQL Server 2012中,您可以使用SUM()计算累积SUM(按NULL顺序分区)。
在SQL Server 2012中,您可以使用: 选择前1 t。* from(select t。,sum(weight)over(按重量分区为NULL的顺序)作为cumweight, 总和(权重)超过(分区为NULL)作为总重量 从T )t 其中rand()(总重量+ 1)&lt; cumweight 通过cumweight desc订购
不幸的是,SQL Server 2008中不支持此语法。在该数据库中,您需要执行自联接,这是您从原始文章中提取的查询。