0

私はすでにこの投稿をここ (http://stackoverflow.com/questions/1398113/sql-select-one-row-randomly-but-taking-into-account-a-weight) で見ましたが、解決できませんでした。「スタッフ」テーブルはどこに置くのですか? RND() の代わりに NEWID() を使用しないのはなぜですか?

テーブルスタッフ

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() を使用する必要はありません

4

1 に答える 1

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

これが行うことは、累積重みを作成してから、重みの合計まで確率変数を作成することです。cum weight が sumweight より小さい最後のレコードが選択されます。「+1」は、最後のレコードであっても、任意のレコードを選択できるようにするためのものです。

SQL Server 2012 では、SUM() over (partition by NULL order by ) を使用して累積 SUM を計算できます。

SQL Server 2012 では、次を使用できます: select top 1 t.* from (select t. , sum(weight) over (partition by NULL order by weight) as cumweight, sum(weight) over (partition by NULL) as totalweight from t ) t where rand() (totalweight+1) < cumweight order by cumweight desc

残念ながら、この構文は SQL Server 2008 ではサポートされていません。そのデータベースでは、元の記事から取得したクエリである自己結合を実行する必要があります。

于 2012-05-20T03:50:03.810 に答える