SQL返回不在表中的随机数

时间:2010-07-09 19:22:05

标签: sql postgresql random

我有一个user_ids表,我们从活动帐户的流数据源中收集了这些表。现在我想查看并填写有关user_ids的信息,这些信息没有做太多任何事情。

是否有SQL(postgres,如果重要)的方式让查询返回表中不存在的随机数?

例如:

SELECT RANDOM(count, lower_bound, upper_bound) as new_id 
WHERE new_id NOT IN (SELECT user_id FROM user_table) AS user_id_table

可能,或者最好用脚本化的包装器生成一堆随机数并将它们传递到数据库中以找出不存在的数据?

5 个答案:

答案 0 :(得分:2)

这是有道理的。如果您希望ID为整数,请尝试:

SELECT trunc((random() * (upper_bound - lower_bound)) + lower_bound) AS new_id 
FROM generate_series(1,upper_bound) 
WHERE new_id NOT IN (
    SELECT user_id 
    FROM user_table)

答案 1 :(得分:1)

您可以将上面的查询包含在子选择中,即

SELECT * FROM (SELECT trunc(random() * (upper - lower) + lower) AS new_id  
FROM generate_series(1, count)) AS x 
WHERE x.new_id NOT IN (SELECT user_id FROM user_table)

答案 2 :(得分:1)

我怀疑你想要随机抽样。我会做类似的事情:

SELECT s
  FROM generate_series(1, (select max(user_id) from users) s
  LEFT JOIN users ON s.s = user_id
 WHERE user_id IS NULL
 order by random() limit 5;

我没有测试过这个,但这个想法应该有效。如果你有很多用户并且没有很多丢失的id,它会比其他选项表现更好,但无论你做什么,性能都可能是个问题。

答案 3 :(得分:0)

可以通过递归查询来完成所需的操作,可惜这不是很好。

假设您有下表:

CREATE TABLE test (a int)

为简化起见,您要插入表中没有的0到4 (random() * 5)::int之间的随机数。

 WITH RECURSIVE rand (i, r, is_new) AS (
  SELECT 
     0,
     null,
     false
  UNION ALL
    SELECT 
      i + 1,
      next_number.v,
      NOT EXISTS (SELECT 1 FROM test WHERE test.a = next_number.v) 
   FROM
     rand r,
     (VALUES ((random() * 5)::int)) next_number(v)
   -- safety check to make sure we do not go into an infinite loop
   WHERE i < 500
)
SELECT * FROM rand WHERE rand.is_new LIMIT 1

我不太确定,但是PostgreSQL一旦有一个结果就应该能够停止迭代,因为它知道查询的限制为1。

关于此查询的一件好事是,您可以将(random() * 5)::int替换为所需的任何ID生成函数

答案 4 :(得分:0)

我的务实方法是:生成500个随机数,然后选择一个不在表中的数字:

WITH fivehundredrandoms AS ( RANDOM(count, lower_bound, upper_bound) AS onerandom
FROM (SELECT generate_series(1,500)) AS fivehundred )
SELECT onerandom FROM fivehundredrandoms 
WHERE onerandom NOT IN (SELECT user_id FROM user_table WHERE user_id > 0) LIMIT 1;