我需要在plpgsql中生成一个随机数,即非重复的随机数。不可重复的数字应在[1,1001]范围内。但是,该代码生成的数字超过1001。
directed2number := trunc(Random()*7+1);
counter := directed2number
while counter > 0
loop
to_point := trunc((random() * 1/directed2number - counter/directed2number + 1) * 1001 +1);
...
...
counter := counter - 1;
end loop;
如果我理解正确
CREATE OR REPLACE FUNCTION x.unique_rand_1001()
RETURNS SETOF integer AS
$body$
DECLARE
nrnr int := trunc(random()*7+1); -- number of numbers
BEGIN
RETURN QUERY
SELECT (1000 * random())::integer + 1
FROM generate_series(1, nrnr*2)
GROUP BY 1
LIMIT nrnr;
END;
$body$ LANGUAGE plpgsql VOLATILE;
通话:
SELECT x.unique_rand_1001();
GROUP BY
使数字唯一。我生成的数字是需要的两倍,以提供足够的数字,以防重复项被删除。对于给定的任务规模(最多1001个数字中的8个),从天文学角度来看,没有足够的数字是不太可能的。最坏的情况:返回观众人数。
我不会在PostgreSQL中那样解决问题。
从软件工程的角度来看,我认为我将分别在x和y之间生成一个随机整数,并生成这些整数的'n',并保证结果是一个集合。
-- Returns a random integer in the interval [n, m].
-- Not rigorously tested. For rigorous testing, see Knuth, TAOCP vol 2.
CREATE OR REPLACE FUNCTION random_integer(integer, integer)
RETURNS integer AS
$BODY$
select cast(floor(random()*($2 - $1 +1)) + $1 as integer);
$BODY$
LANGUAGE sql VOLATILE
然后选择一个介于1和1000之间的随机整数,
select random_integer(1, 1000);
要选择1到1000之间的100个随机整数,
select random_integer(1, 1000)
from generate_series(1,100);
您可以保证应用程序代码或数据库中的唯一性。 Ruby实现了一个Set
类。其他语言在各种名称下也具有类似的功能。
在数据库中执行此操作的一种方法是使用本地临时表。 Erwin的权利是需要生成比您需要的更多的整数,以补偿删除重复项。此代码生成20,并按插入顺序选择前8行。
create local temp table unique_integers (
id serial primary key,
n integer unique
);
insert into unique_integers (n)
select random_integer(1, 1001) n
from generate_series(1, 20)
on conflict (n) do nothing;
select n
from unique_integers
order by id
fetch first 8 rows only;