我有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开始,我了解了window
和partition
。所以我试过下面的查询。
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
都是我的输出。
答案 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
值。
答案 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;