为每一行选择随机值

时间:2017-09-22 21:31:01

标签: sql postgresql random

我正在尝试从另一个表中的列中为我正在更新的表的每一行选择一个新的随机值。我得到了随机值,但是我不能让它改变每一行。有任何想法吗?这是代码:

UPDATE srs1.courseedition
SET ta_id = teacherassistant.ta_id
FROM srs1.teacherassistant
WHERE (SELECT ta_id FROM srs1.teacherassistant ORDER BY RANDOM()
       LIMIT 1) = teacherassistant.ta_id

2 个答案:

答案 0 :(得分:0)

我的猜测是Postgres正在优化子查询,因为它对外部查询没有依赖性。您是否只考虑使用子查询?

UPDATE srs1.courseedition ce
    SET ta_id = (SELECT ta.ta_id
                 FROM srs1.teacherassistant ta
                 WHERE ce.ta_id IS NULL  -- or something like that
                 ORDER BY RANDOM()
                 LIMIT 1
                );

我认为这不会解决问题(聪明的优化者,唉)。但是,如果您与外部查询相关联,那么它应该每次都运行。也许:

WHERE

您可以将WHERE COALESCE(ca.ta_id, '') IS NOT NULL子句替换为更加荒谬的内容,例如/dev/snd/by-id

答案 1 :(得分:0)

以下解决方案应该比按行数量更快<强>比为每行运行相关子查询。 N 随机排序整个表格与 1 随机排序。结果同样是随机的,但我们使用此方法得到完全均匀的分布,而Gordon's solution中的独立随机选择可以(并且可能会)比其他更频繁地分配某些行。有各种各样的“随机”。 “随机性”的实际要求需要仔细定义。

假设courseedition中的行数大于teacherassistant中的行数。

更新courseedition中的所有行:

UPDATE srs1.courseedition c1
SET    ta_id = t.ta_id
FROM  (
   SELECT row_number() OVER (ORDER BY random()) - 1 AS rn  -- random order
        , count(*) OVER () As ct                           -- total count
        , ta_id
   FROM   srs1.teacherassistant           -- smaller table
   ) t
JOIN (
   SELECT row_number() OVER () - 1 AS rn  -- arbitrary order
        , courseedition_id                -- use actual PK of courseedition
   FROM   srs1.courseedition              -- bigger table
   ) c ON c.rn%t.ct = t.rn                -- rownumber of big modulo count of small table
WHERE  c.courseedition_id = c1.courseedition_id;

注释

将较大表的随机rownumber与较小表的计数模拟为较小表的rownumber。

row_number() - 1获取基于0的索引。允许更优雅地使用模运算符%

一个表的随机排序就足够了。较小的桌子更便宜。第二个可以有任何顺序(任意更便宜)。连接后的赋值是随机的。如果在较大的表的排序顺序中存在规则模式,则仅间接地损害完美随机性。在这种不太可能的情况下,将ORDER BY random()应用于更大的表以消除任何此类影响。