Sql 聚合函数,用于按顺序获取两行的差值或比率

Sql 聚合函数,用于按顺序获取两行的差值或比率,sql,postgresql,aggregate-functions,greatest-n-per-group,window-functions,Sql,Postgresql,Aggregate Functions,Greatest N Per Group,Window Functions,我有一张满是价格、项目和日期的桌子。这方面的一个例子是: AA, 1/2/3024, 1.22 AA, 1/3/3024, 1.23 BB, 1/2/3024, 4.22 BB, 1/3/3024, 4.23 在数据中,每个价格只有两行,它们是按日期排序的。如何将此数据集压缩为一个产品行,显示上一个价格与上一个价格的差异?[这也适用于比率,因此AA将产生1.23/1.22] 结果应该是这样的 AA, todays price-yesterdays price 尽管是求和函数,但列表上没有减法

我有一张满是价格、项目和日期的桌子。这方面的一个例子是:

AA, 1/2/3024, 1.22
AA, 1/3/3024, 1.23
BB, 1/2/3024, 4.22
BB, 1/3/3024, 4.23
在数据中,每个价格只有两行,它们是按日期排序的。如何将此数据集压缩为一个产品行,显示上一个价格与上一个价格的差异?[这也适用于比率,因此AA将产生1.23/1.22]

结果应该是这样的

AA, todays price-yesterdays price
尽管是求和函数,但列表上没有减法函数


我使用的是postgres 9.1。

如果每个项目只有两行,那么

SELECT item, MAX(price) - MIN(price) AS diff, MAX(price) / MIN(price) AS ratio
FROM yourtable
GROUP BY item

就可以了。

如果每个项目只有两行,那么

SELECT item, MAX(price) - MIN(price) AS diff, MAX(price) / MIN(price) AS ratio
FROM yourtable
GROUP BY item
select product,
       sales_date,
       current_price - prev_price as diff
from (
  select product,
         sales_date, 
         price as current_price,
         lag(price) over (partition by product order by sales_date) as prev_price,
         row_number() over (partition by product order by sales_date desc) as rn
  from the_unknown_table
) t
where rn = 1;
我会成功的

select product,
       sales_date,
       current_price - prev_price as diff
from (
  select product,
         sales_date, 
         price as current_price,
         lag(price) over (partition by product order by sales_date) as prev_price,
         row_number() over (partition by product order by sales_date desc) as rn
  from the_unknown_table
) t
where rn = 1;
SQLFiddle示例:


SQLFiddle示例:

因为每个价格只有两行,所以这可以更简单、更快:

SELECT n.item, n.price - o.price AS diff, n.price / o.price AS ratio
FROM   price n                 -- "new"
JOIN   price o USING (item)    -- "old"
WHERE  n.day > o.day;

此表单还有一个额外的好处,即您可以直接使用两行中的所有列


对于更复杂的场景(这不是必需的),您可以使用已经指出的窗口函数。这里有一个比建议的更简单的方法:

SELECT DISTINCT ON (item)
       item
      ,price - lead(price) OVER (PARTITION BY item ORDER BY day DESC) AS diff
FROM   price
ORDER  BY item, day DESC;

这里只需要一个窗口函数。和一个查询级别,因为在窗口函数之后应用。窗口中的排序顺序与总体排序顺序一致,有助于提高性能。

由于每个价格只有两行,因此这可以更简单、更快:

SELECT n.item, n.price - o.price AS diff, n.price / o.price AS ratio
FROM   price n                 -- "new"
JOIN   price o USING (item)    -- "old"
WHERE  n.day > o.day;

此表单还有一个额外的好处,即您可以直接使用两行中的所有列


对于更复杂的场景(这不是必需的),您可以使用已经指出的窗口函数。这里有一个比建议的更简单的方法:

SELECT DISTINCT ON (item)
       item
      ,price - lead(price) OVER (PARTITION BY item ORDER BY day DESC) AS diff
FROM   price
ORDER  BY item, day DESC;

这里只需要一个窗口函数。和一个查询级别,因为在窗口函数之后应用。窗口中的排序顺序与总体排序顺序一致,有助于提高性能。

这不起作用,因为差异必须基于日期。又名今天的价格-昨天的价格。这不起作用,因为差异必须基于日期。又名今天的价格-昨天的价格。我花了一段时间才明白需要什么行号,但现在我明白了第三条评论。。但是使用order by和order by desc是相当聪明的。起初我认为这是一个错误。我花了一些时间才理解需要什么行号,但现在我明白了第三条注释。。但是使用orderby和orderbydesc是相当聪明的。起初我认为这是一个错误。