如何从每个组的上一行获取列值?

时间:2014-01-31 13:20:11

标签: sql postgresql

请阅读问题,不重复。

我会尝试正确解释问题:

我有一张这样的表:

Table: stg_mov_salida

id_movement | id_product | id_warehouse | movement_date | id_sale | sale_value | ...
209338          54545          2          "2011-05-21"    163299     75.95
209306          54545          2          "2011-06-05"    163267     75.95
209347          54545          2          "2012-10-26"    163308     77.95
209399          54545          3          "2011-01-22"    163360     79.95
209302          54545          3          "2011-01-23"    163263     72.95
209304          54545          3          "2011-01-24"    163265     72.95

我希望得到上一行的sale_value,但前提是前一行属于与当前行相同的id_productid_warehouse

stg_mov_salida是按以下顺序排序的临时表:

 id_product asc, id_warehouse asc, movement_date asc

正如我读过其他问题(如this或类似问题),我试图这样做但没有成功。我尝试过的最后一个查询(也是最接近我的解决方案)是:

SELECT x2.*,
   (SELECT x2.sale_value AS last_sale_value
            FROM stg_mov_salida ms 
                WHERE x2.id_product = ms.id_product 
                AND x2.id_warehouse = ms.id_warehouse
                AND x2.date_movement  > ms.date_movement 
            ORDER BY ms.id_product asc, 
                             ms.id_warehouse asc, 
                             ms.date_movement asc
            LIMIT 1)
FROM stg_mov_salida x2

但是这个查询是如此之慢以至于我从未见过它完成,即使只有一个给定id_product,因此如果这个查询是正确的,我就不能使用它,因为它太慢了。

任何人都知道如何解决我的问题?

更新

预期结果:

id_movement | id_product | id_ware | mov_date | id_sale | sale_value | prev_sale_value
  209338       54545          2    "2011-05-21"  163299     75.95           null
  209306       54545          2    "2011-06-05"  163267     75.95           75.95
  209347       54545          2    "2012-10-26"  163308     77.95           75.95
  209399       54545          3    "2011-01-22"  163360     79.95           null
  209302       54545          3    "2011-01-23"  163263     72.95           79.95
  209304       54545          3    "2011-01-24"  163265     72.95           72.95

null上的prev_sale_value值是因为该行是(id_product, id_warehouse)组中的第一行,但我们的想法是将null替换为sale_value 1}}直接在同一行,但是当我为每一行得到正确的prev_sale_value时,我会这样做。

任何帮助将不胜感激

为了便于回复,这里是SQLFiddle

我也尝试了这个查询,但它无法正常运行:

select x2.*,
lag(sale_value, 1) over (partition by sale_value
                                order by id_product asc,
                                id_warehouse asc,
                                date_movement asc) as last_sale_value

from stg_mov_salida x2
order by id_product asc, id_warehouse asc, date_movement asc

1 个答案:

答案 0 :(得分:1)

使用lag是正确的方法,但你的论点是错误的。如你所说:

  

我想得到前一行的sale_value,但前提是前一行属于同一个id_product,而id_warehouse属于当前行。

这意味着您的partiton by条款应包含id_productid_warehouse

select x2.*,
lag(sale_value, 1) over (partition by id_product asc, id_warehouse asc
                         order by date_movement asc) as last_sale_value    
from stg_mov_salida x2
order by id_product asc, id_warehouse asc, date_movement asc