PostgreSQL select 最大行数
PostgreSQL select max from rows
我有以下数据:
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
我还不能现场试用。
您可以使用 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;
请记住,如果有 2 个或更多 product_id
创建日期不同但最高 amount
相同,它们将全部返回。
在 ORDER BY
中使用位置不是最佳做法。
如果我没理解错的话,你可以用distinct on
:
select distinct on (product_id) o.*
from offers o
order by product_id, amount desc;
distinct on
是一个 Postgres 扩展。在这种情况下,它 returns 每 product_id
一行。特定行是金额最大的行,由 amount desc
.
确定
试试这个:
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
您可以使用 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 您想要的行:
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)
我有以下数据:
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
我还不能现场试用。
您可以使用 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;
请记住,如果有 2 个或更多 product_id
创建日期不同但最高 amount
相同,它们将全部返回。
在 ORDER BY
中使用位置不是最佳做法。
如果我没理解错的话,你可以用distinct on
:
select distinct on (product_id) o.*
from offers o
order by product_id, amount desc;
distinct on
是一个 Postgres 扩展。在这种情况下,它 returns 每 product_id
一行。特定行是金额最大的行,由 amount desc
.
试试这个:
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
您可以使用 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 您想要的行:
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)