输入示例:

SELECT * FROM test;
 id | percent   
----+----------
  1 | 50 
  2 | 35   
  3 | 15   
(3 rows)

你会如何编写这样的查询,平均50%的时间我可以得到id=1的行,35%的时间行id=2,15%的时间行id=3

我try 了SELECT id FROM test ORDER BY p * random() DESC LIMIT 1个,但结果不正确.在SELECT id FROM test ORDER BY p * random() DESC LIMIT 100次运行后,我得到了一个类似于:{1=6293, 2=3302, 3=405}的分布,但我预计分布将接近:{1=5000, 2=3500, 3=1500}.

有什么 idea 吗?

推荐答案

这应该可以做到:

WITH CTE AS (
    SELECT random() * (SELECT SUM(percent) FROM YOUR_TABLE) R
)
SELECT *
FROM (
    SELECT id, SUM(percent) OVER (ORDER BY id) S, R
    FROM YOUR_TABLE CROSS JOIN CTE
) Q
WHERE S >= R
ORDER BY id
LIMIT 1;

子查询Q给出以下结果:

1  50
2  85
3  100

然后,我们只需生成一个范围为[0,WHERE]的随机数,并 Select 第一行等于或超过该数字(WHERE子句).我们使用公共表表达式(WITH)来确保只计算一次随机数.

BTW, the 100 allows you to have any weights in 101 - they don't strictly need to be percentages (i.e. add-up to 100).

[SQL Fiddle]

Postgresql相关问答推荐

Postgres-pgloader-默认情况下,在PostgreSQL中将列名转换为小写

如何在PostgreSQL中以行值的形式获取列

时间戳的postgreSQL-to_char如果为零,则不显示微秒

将整数(以毫秒为单位的epoch时间)转换为PrimitiveDateTime

我应该如何更新热门表?

Postgres 使用不同元素数据类型的订单数据

TimescaleDB 连续聚合:如何存储连续聚合结果

连接 Supbase Postgresql 数据库时,Stepzen Graphiql 资源管理器中的主机名解析错误

postgresql查询中的正则表达式不区分大小写

postgreSQL 中对 utf-8 的 LC_COLLATE 和 LC_CTYPE 支持

从左连接更新 Postgres

在函数中返回字段作为插入结果

Psycopg2 使用占位符插入表格

如何在数据库表中查找重复条目?

在 PostgreSQL 中的表上禁用 DELETE?

SqlAlchemy:多列的不同计数

PostgreSQL 条件 where 子句

PostgreSQL 9 在 Windows 上安装:Unable to write inside TEMP environment path.

SQL:子查询的列太多

判断 Postgres 中是否存在序列(plpgsql)