我想在 Postgres 中运行一个查询,该查询按预期返回结果集(比如SELECT * FROM products ORDER BY created_at DESC
),但是稍微打乱结果,这样你就不会有太多连续的结果共享相同的supplier_id
值。
这一点尤其重要,因为每个供应商的产品往往在大致相同的时间进口,制造created_at
相同,这意味着几页结果通常只有 1 个供应商的产品。
你怎么混?
我想在 Postgres 中运行一个查询,该查询按预期返回结果集(比如SELECT * FROM products ORDER BY created_at DESC
),但是稍微打乱结果,这样你就不会有太多连续的结果共享相同的supplier_id
值。
这一点尤其重要,因为每个供应商的产品往往在大致相同的时间进口,制造created_at
相同,这意味着几页结果通常只有 1 个供应商的产品。
你怎么混?
如果我最终正确理解了您的问题,则窗口功能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
in 子句是可选的,OVER
但它在我使用 Postgres 9.1 的测试中加快了执行速度,因为它与 finalORDER BY
子句同步。
最多可以X
同时选择来自同一供应商的行。如果您需要真正的随机选择,则必须在子句random()
中另外排序。OVER
除此之外,这不是“随机化”或“重新洗牌”,而是抑制多余的行。如果您希望显示这些行(超过X
),则必须定义排序顺序中的位置。不过,这将不可避免地打破时间顺序。
我的理解是,您希望按时间顺序对结果进行排序,但是对于 的特定值created_at
,只有一个不同的值,supplier_id
并且您希望有多个值,假设它们在排序列表中足够接近。
关键问题是 的分辨率created_at
,无论它是什么(timestamp
具有亚秒级分辨率,timestamp(0)
将具有一秒的分辨率)在直接用作排序标准时都太高了。
您可以尝试按时间范围排序。例如:
ORDER BY (extract(epoch from created_at)/3600)::int, RANDOM()
将首先按插入条目的小时数(3600 秒)排序,测量为自 70 年 1 月 1 日以来经过的小时数,然后使用二级排序(随机)随机排列此范围内的结果。如果在同一小时内插入不同供应商的可能性仍然太小,则将其设置为几个小时或几天。