我有产品,发票和客户。在客户发票上是一个没有税的销售价格的产品。我需要为每个客户报告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
答案 0 :(得分:3)
将window functions与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)
答案 1 :(得分:0)
我认为,要从第一张发票中获得售价,您需要有关sale_date的信息或您未在请求中说明的有效条件。
有不同的方法可以实现这个结果,但我喜欢的方法只基于聚合函数。以下示例使用postges,但其他DB也可以为您提供相同的功能。
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=#