Postgres 获得单个供应商的第一个和最后一个版本

Postgres get first and last version for individual vendor

我有 RFQ(报价请求)和供应商投标金额与版本的映射 table。

Table :

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 

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

rfq_id=1 的预期输出:

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

我开始了解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

您必须 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

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

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

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

如果没有 ORDER BY,OLAP 函数默认为 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING,但如果有 ORDER BY,这将更改为 ROW UNBOUNDED PRECEDING

你很接近,但你需要两个不同的windows:

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;