2013-02-12 22 views
-1

我想在Postgres中运行一个按预期方式返回结果集的查询(比如说SELECT * FROM products ORDER BY created_at DESC),但将结果稍微调整一下,这样就不会有太多连续的结果共享supplier_id值。随机化查询结果共享某个属性

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

你怎么混在一起的?

+0

你是否希望每个供应商中只有一个出现在这个洗牌数据集中,或者重复供应商都可以,只要他们不是“太频繁”? – 2013-02-12 15:05:52

+0

您是否缩进以**随机**订购 – frictionlesspulley 2013-02-12 15:06:31

+0

重复可以,但不会太频繁。我只是不希望具有相同'supplier_id'的X产品连续出现。 – Avishai 2013-02-12 15:07:39

回答

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 

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

最多可以同时从同一供应商处选择X行。如果您需要真正的随机选择,则必须在OVER子句中额外订购random()

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

0

我的理解是要以时间顺序排序结果,但对于created_at特定的值,只有一个supplier_id不同的价值,你会希望有一些相反,假设他们在也非常接近排序列表。直接作为排序标准时

的关键问题将是的created_at分辨率,无论是它(timestamp具有亚秒级分辨率,timestamp(0)将有一秒的分辨率)太高。

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

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

会命令首先由小时(3600秒)插入的条目,如自1/1/70的经过的小时数来测量,然后洗牌内部这一范围的结果与次级排序(随机)。如果在同一个小时内插入不同供应商的可能性仍然很小,则需要几个小时或几天。