从考虑了重量的记录中选择TOP 1

时间:2012-05-20 01:22:23

标签: sql sql-server sql-server-2008 sql-server-2012

我已在此处看到此帖(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()

1 个答案:

答案 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中不支持此语法。在该数据库中,您需要执行自联接,这是您从原始文章中提取的查询。