我有以下数据:
CREATE TABLE offer (
id INTEGER,
product_id VARCHAR,
created_at TIMESTAMP,
amount INTEGER,
PRIMARY KEY (id));
INSERT INTO offer (id, product_id, created_at, amount)
VALUES
(1, '123', '2016-03-12', 990),
(2, '136', '2016-02-01', 1056),
(3, '111', '2016-01-01', 1000),
(4, '123', '2016-01-02', 500);
我想获得每个product_id数量最多的行。 如果我采用这些先前的行,我想获得ID:2,3和1,因为第1行包含的数量大于第4行。
id | product_id | created_at | amount
----+------------+---------------------+--------
2 | 136 | 2016-02-01 00:00:00 | 1056
3 | 111 | 2016-01-01 00:00:00 | 1000
1 | 123 | 2016-03-12 00:00:00 | 990
我尝试过类似的东西,但我不确定:
SELECT id, product_id, created_at, amount
FROM offer
ORDER BY 4, 2 DESC, 1, 3
我现在还不能尝试。
答案 0 :(得分:1)
您可以使用RANK()
:
WITH cte AS
(
SELECT * , RANK() OVER (PARTITION BY product_id ORDER BY amount DESC) AS rnk
FROM Offers
)
SELECT id, product_id, created_at, amount
FROM cte
WHERE rnk = 1
ORDER BY amount DESC;
的 LiveDemo
强>
请注意,如果有2个或更多product_id
创建了不同的日期,但相同的最高amount
将全部返回。
在ORDER BY
中使用位置不是最佳做法。
答案 1 :(得分:1)
如果我理解正确,您可以使用distinct on
:
select distinct on (product_id) o.*
from offers o
order by product_id, amount desc;
distinct on
是Postgres扩展程序。在这种情况下,它每product_id
返回一行。特定行是具有最大金额的行,由amount desc
确定。
答案 2 :(得分:1)
您可以使用PARTITION
和RANK
使用复杂条件生成排名:
SELECT
id,
product_id,
created_at,
amount,
RANK() OVER (
PARTITION BY product_id
ORDER BY amount DESC
) AS amount_rank_by_product_id
FROM offer
ORDER BY
product_id ASC,
amount_rank_by_product_id ASC
;
id | product_id | created_at | amount | amount_rank_by_product_id
----+------------+---------------------+--------+---------------------------
3 | 111 | 2016-01-01 00:00:00 | 1000 | 1
1 | 123 | 2016-03-12 00:00:00 | 990 | 1
4 | 123 | 2016-01-02 00:00:00 | 500 | 2
2 | 136 | 2016-02-01 00:00:00 | 1056 | 1
(4 rows)
然后,您可以使用生成的排名来选择所需的行:
SELECT
o.id,
o.product_id,
o.created_at,
o.amount
FROM
offer AS o
INNER JOIN (
SELECT
id,
product_id,
RANK() OVER (
PARTITION BY product_id
ORDER BY amount DESC
) AS amount_rank
FROM offer
) AS ar
USING (id)
WHERE
ar.amount_rank = 1
ORDER BY
o.amount DESC,
o.product_id ASC
;
id | product_id | created_at | amount
----+------------+---------------------+--------
2 | 136 | 2016-02-01 00:00:00 | 1056
3 | 111 | 2016-01-01 00:00:00 | 1000
1 | 123 | 2016-03-12 00:00:00 | 990
(3 rows)
答案 3 :(得分:0)
试试这个:
SELECT o.*
FROM offer o
LEFT JOIN offer o1 ON o1.amount > o.amount AND o.product_id = o1.product_id
WHERE o1.amount IS NULL