Как получить значение из первой строки сгруппированной детали? - PullRequest
1 голос
/ 24 марта 2012

У меня есть товары, счета и клиенты. На счет клиента выставляется товар с продажной ценой без налога. Мне нужно сообщить для каждого клиента, за product_id =45, самую низкую цену продажи, а также цену продажи с самого первого счета.

Я могу сгруппировать все, кроме последнего условия. Я знаю, что это можно сделать с subselect, но я бы хотел их избежать.

Упрощенная структура базы данных:

table clients
-clent_id serial

table products
-product_id serial
-name text

table invoices
-invoice_id serial
-client_id int

table invoices_rows
-invoice_row_id serial
-invoice_id int
-product_id int
-price double precision

Ответы [ 2 ]

3 голосов
/ 24 марта 2012

Используйте оконные функции в сочетании с DISTINCT, чтобы получить самую низкую и первую цену одновременно (без подвыбора в соответствии с запросом):

SELECT DISTINCT ON (i.client_id)
       i.client_id
     , min(ir.price) OVER (PARTITION BY i.client_id) AS min_price
     , first_value(ir.price) OVER (PARTITION BY i.client_id
                                   ORDER BY ir.invoice_id) AS first_price
FROM   invoices_rows ir
JOIN   invoices i USING (client_id)
WHERE  ir.product_id = 45;

Применить DISTINCT ON (client_id), чтобы получить только один ряд на client_id.DISTINCT применяется после оконных функций, в то время как GROUP BY будет применяться раньше.

Я предполагаю, что «первый счет» можно интерпретировать как «самый низкий invoice_id».Вам нужна «самая низкая цена продажи» для каждого клиента?Или общая самая низкая цена на товар?Я изменил на "per client_id" сейчас.Кажется более вероятным.


Если вы не возражаете против выбора или CTE, это, вероятно, будет работать лучше:

WITH x AS (
    SELECT i.client_id
         , min(ir.price) AS min_price
         , min(ir.invoice_id) AS invoice_id
    FROM   invoices_rows ir
    JOIN   invoices i USING (client_id)
    WHERE  ir.product_id = 45
    )
SELECT x.*, ir.price AS first_price
FROM   x
JOIN   invoices_rows ir USING (invoice_id)
0 голосов
/ 24 марта 2012

Я думаю, что для получения продажной цены по самому первому счету вам потребуется информация о дате продажи или действительных критериях, которые вы не указали в своем запросе.

Существуют различные способы достижения этого результата, но тот, который я предпочитаю, основан только на агрегатных функциях.В следующем примере используются postges , но и другие БД могут предоставлять вам те же функции.

postgres=# select *
postgres-# from prices_products;
 product_name | customer_name | price | sell_date
--------------+---------------+-------+------------
 knife        | mark          |   100 | 2011-01-20
 book         | cris          |    20 | 2011-05-12
 book         | mark          |    25 | 2010-09-30
 book         | cris          |    30 | 2012-02-15
(4 rows)


postgres=#
postgres=# select product_name, customer_name,m as maximum, arr[1] as first_date_val
postgres-# from (
postgres(#              select product_name, customer_name, max(price) as m, array_agg(price order by sell_date) as arr
postgres(#              from prices_products
postgres(#              group by product_name, customer_name
postgres(#      ) a;
 product_name | customer_name | maximum | first_date_val
--------------+---------------+---------+----------------
 book         | cris          |      30 |             20
 book         | mark          |      25 |             25
 knife        | mark          |     100 |            100
(3 rows)


postgres=#
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...