选择时间戳作为聚合函数

时间:2019-02-13 13:45:49

标签: sql postgresql

我有两个表:

products
id | actual_price

prices_history
id| product_id| price| timestamp

products.id = prices_history.product_id

我需要select products.id, max(prices_history.price) and one latest timestamp for max(prices_history.price).

我尝试了以下方法:

SELECT p.id, max_price, actual_price, max_price_time                       
FROM products p                                                
JOIN (SELECT max(price) as max_price, product_id
      FROM prices_history                              
      WHERE timestamp > '2019-02-01'                             
      GROUP BY product_id) h                             
      ON  h.product_id = p.id
JOIN (SELECT timestamp as max_price_time,  product_id, price                           
      FROM prices_history
      ORDER BY timestamp DESC LIMIT 1) h2                            
      ON  h2.product_id = p.id AND h2.price = max_price;

但是它什么也不返回

有趣的是,没有第二个JOIN,我得到了很多结果。因此,我猜想第二个JOIN中的ORDER BY时间戳记DESC LIMIT 1会破坏所有内容。 但是如果没有LIMIT,我不知道如何只获得价格最高的最新时间戳?

3 个答案:

答案 0 :(得分:0)

我认为您只想要distinct on

select distinct on (ph.product_id) ph.*
from prices_history ph
order by price desc, timestamp desc

答案 1 :(得分:0)

使用row_number()

  withe cte as

 (  SELECT p.*,ph.*,
   row_number()over(partition by p.id order by  timestamp desc,price desc)rn                     
    FROM products p join prices_history ph on p.id = ph.product_id
 ) select * from cte where rn=1

答案 2 :(得分:0)

我猜您的问题在于您的第二个子查询不使用任何过滤器,并且您基本上总是找到相同的最新时间戳(在所有时间戳中,不仅是针对该产品),这与实际情况不符使用任何maximum_prices(因此每个产品的最高价格都不会在最新时间戳记上显示)。

无视我以前的回答。可能是因为我有一段时间没有接触过纯SQL了,但是我无法通过对单个查询进行分组来实现该逻辑(试图在Postgress SQLfiddle中实现)。我可能发誓我可以按组中的最大值筛选一组查询。...无论如何,我尝试重写该查询,现在我明白了为什么您使用后继查询。

这仍然是完全相同的问题(没有过滤器)。将分组添加到第二个子查询可解决此问题。 SQLfiddle code进行演示:

select p1.id, p1.max_price, p2.max_date 
from ( select id, max(price) as max_price from prod group by id ) as p1  
  inner join  ( select id, price, max(date) as max_date from prod group by id, price ) as p2 
    on p1.id = p2.id and p1.max_price = p2.price

此时,在前两个子查询之前添加另一个内部联接应该足够简单。