我有一个包含几列(id,description,created(时间戳(和ipaddress(的表。我已经插入了 200 行作为虚拟数据。我需要一种方法来从该表中抽取 88 个没有重复项的随机行。
我试过这个:
create or replace function GetRandomCrazy88() returns setof varchar(255) as
'
select description
from task
left join tagassignment t on task.id = t.taskid
order by random()
limit 88;
' language 'sql';
但这会返回重复的行。
我也试过这个(它有点失控(:
CREATE OR REPLACE FUNCTION GetRandomCrazy88(amount INTEGER)
RETURNS SETOF VARCHAR(255) AS
$$
DECLARE
tasklist INTEGER[] := '{}'::INTEGER[];
randomid INTEGER;
counter INTEGER := 0;
BEGIN
WHILE counter <= amount LOOP
SELECT CASE WHEN id = 0 THEN 1 ELSE id END INTO randomid
FROM ROUND(RANDOM() * (SELECT COUNT(*) - 1 FROM task)) AS id;
IF randomid = ANY(tasklist) OR ARRAY_LENGTH(tasklist, 1) IS NULL THEN
tasklist = array_append(tasklist, randomid);
counter := counter + 1;
ELSE
RAISE NOTICE 'DUPLICATE ID!!!';
END IF;
END LOOP;
RETURN QUERY SELECT description
FROM task t
WHERE t.id = ANY(tasklist);
END;
$$ LANGUAGE plpgsql
SECURITY DEFINER;
它在 while 循环中失败。它永远不会达到所需的 88 个数字,因为它无法在 if 语句中向数组添加任何内容,因为数组为空且具有 NULL 值。
有什么方法可以得到正好 88 个随机行,没有任何重复项?
以下是您可能喜欢的快速解决方案:
CREATE EXTENSION IF NOT EXISTS tsm_system_rows;
select * from task
tablesample system_rows (88);
作为参考,TABLESAMPLE 在 SELECT 的文档中: https://www.postgresql.org/docs/current/sql-select.html
这是该功能的一个很好的文章:
https://www.2ndquadrant.com/en/blog/tablesample-in-postgresql-9-5-2/
。以及同一作者关于随机抽样的一般主题的另一篇文章:
https://www.2ndquadrant.com/en/blog/tablesample-and-other-methods-for-getting-random-tuples/
tsm_system_rows是两个标准采样扩展之一,记录如下: https://www.postgresql.org/docs/current/tsm-system-rows.html
嘿!我很高兴你问了这个问题。我倾向于使用BERNOULLI方法,该方法内置于SELECT中,但它基于百分比。我刚刚尝试了这个,它工作正常:
select * from task
tablesample BERNOULLI (1)
limit 88