Postgres获取个别供应商的第一个和最后一个版本

时间:2016-11-10 06:11:24

标签: sql postgresql hibernate ejb

我有RFQ(报价请求)的映射表和供应商的出价金额。

表:

id  rfq_id(FK)  vendor_id(FK)   amount  version
-----------------------------------------------

 1      1           1            100      1
 2      1           1            90       2
 3      1           1            80       3
 4      1           2            50       1
 5      1           7            500      1
 6      1           7            495      2
 7      1           7            500      3
 8      1           7            525      4
 9      1           7            450      5
 10     1           7            430      6 
 11     2           1            200      1
 12     2           2            300      1
 13     2           2            350      2
 14     2           3            40       1
 15     3           4            70       1 

在上表中,我想分析供应商对特定rfq_id的第一次和最后一次出价。

rfq_id的预期输出= 1:

vendor_id   first_bid   last_bid
---------------------------------
    1           100         80
    2           50          50
    7           500         430

Postgres : get min and max rows count in many to many relation table开始,我了解了windowpartition。所以我试过下面的查询。

SELECT 
  vendor_id,
  version,
  amount,
  first_value(amount) over w as first_bid,
  last_value(amount) over w as last_bid,
  row_number() over w as rn
FROM   
   rfq_vendor_version_mapping
where
   rfq_id=1
   WINDOW w AS (PARTITION BY vendor_id order by version)
ORDER by vendor_id;

通过上述查询,每个供应商的最大rn都是我的输出。

http://sqlfiddle.com/#!15/f19a0/7

3 个答案:

答案 0 :(得分:3)

窗口函数列添加到所有现有行,而不是将输入行分组到单个输出行中。由于您只对出价值感兴趣,因此请在感兴趣的字段中使用DISTINCT子句。

请注意,WINDOW定义需要frame clause才能确保考虑分区中的所有行。默认情况下,分区中的帧(计算中使用的行)从分区的开头到当前行。因此,last_value()窗口函数始终返回当前行的值;使用UNBOUNDED PRECEDING TO UNBOUNDED FOLLOWING的框架将框架扩展到整个分区。

SELECT DISTINCT
  vendor_id,
  version,
  amount,
  first_value(amount) OVER w AS first_bid,
  last_value(amount) OVER w AS last_bid
  row_number() over w as rn
FROM   
   rfq_vendor_version_mapping
WHERE rfq_id = 1
WINDOW w AS (PARTITION BY vendor_id ORDER BY version
             ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
ORDER BY vendor_id;

答案 1 :(得分:2)

您必须GROUP BY vendor_id因为每vendor_id只需要一行:

SELECT 
  vendor_id,
  MAX(CASE WHEN rn = 1 THEN amount END) AS first_bid,
  MAX(CASE WHEN rn2 = 1 THEN amount END) AS last_bid
FROM (  
   SELECT 
     vendor_id,
     version,
     amount,
     row_number() over (PARTITION BY vendor_id order BY version) as rn,
     row_number() over (PARTITION BY vendor_id order BY version DESC) as rn2
   FROM   
      rfq_vendor_version_mapping
   WHERE
      rfq_id=1) AS t
GROUP BY vendor_id 
ORDER by vendor_id;

该查询使用条件聚合来提取与第一次和最后一次出价相对应的amount值。

Demo here

答案 2 :(得分:-1)

如果没有ORDER BY OLAP功能默认为ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING,但ORDER BY此更改为ROW UNBOUNDED PRECEDING

你很亲密,但你需要两个不同的窗口:

select vendor_id, amount as first_bid, last_bid
from 
 (
    SELECT 
      vendor_id,
      version,
      amount,
      last_value(amount) -- highest version's bid
      over (PARTITION BY vendor_id 
            order by version
            rows between unbiunded preceding and unbounded following) as last_bid,
      row_number()
      over (PARTITION BY vendor_id 
            order by version) as rn
    FROM   
       rfq_vendor_version_mapping
    where
       rfq_id=1 
 ) as dt
where rn = 1 -- row with first version/bid
ORDER by vendor_id;