随机化共享特定属性的查询结果

时间:2013-02-12 15:04:06

标签: sql postgresql

我想在Postgres中运行一个查询,按预期返回结果集(比如SELECT * FROM products ORDER BY created_at DESC),但是稍微改变一下结果,这样就不会有太多连续的结果共享相同的结果supplier_id值。

这一点尤其重要,因为每个供应商的产品往往大致在同一时间进口,因此created_at相同,这意味着几页结果通常只有一个供应商的产品。

你如何混淆它?

2 个答案:

答案 0 :(得分:1)

如果我最终理解你的问题,那么window function row_number()应该做正确的工作PARTITION

SELECT *
FROM  (
   SELECT *, row_number() OVER (PARTITION BY created_at, supplier_id
                                ORDER BY created_at DESC) AS rn
   FROM   products
   ) a
WHERE  rn <= X
ORDER  BY created_at DESC

ORDER BY子句中的OVER是可选的,但它加快了我在Postgres 9.1测试中的执行速度,因为它与最终的ORDER BY子句同步。

同时选择同一供应商的最多X行。如果您需要真正随机选择,则必须在random()条款中另外按OVER订购。

除此之外,这不是“随机化”或“重新洗牌”,而是抑制多余的行。如果您希望显示这些行(超过X),则必须在排序顺序中定义位置。但是,它不可避免地会破坏时间顺序。

答案 1 :(得分:0)

我的理解是,您希望按时间顺序对结果进行排序,但对于created_at的特定值,只有一个不同的supplier_id值,而您希望有几个而不是假设它们在排序列表中足够接近。

关键问题是created_at的分辨率,无论它是什么(timestamp具有亚秒级分辨率,timestamp(0)具有一秒的分辨率)都太高了直接用作排序标准。

您可以尝试按时间范围排序。例如:

ORDER BY (extract(epoch from created_at)/3600)::int, RANDOM()

将首先按小时(3600秒)排序插入条目,测量为自1970年1月1日以来经过的小时数,然后使用辅助排序(随机)将结果随机排列在此范围内。如果在同一小时内插入不同供应商的可能性仍然太小,可以使用几个小时或几天。