2016-11-10 1 views
3

У меня есть таблица отображения для запроса предложений (запрос на цитату) и сумма предложения продавца с версией.Postgres получить первую и последнюю версию для отдельного поставщика

Таблица:

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 мой выход.

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

ответ

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;
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

-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; 
Смежные вопросы