Postgres - 按用户对行进行分组,每组中每个用户返回一行

Mon*_*ock 6 sql postgresql

我有一张purchases桌子:

-----------------
user_id | amount
-----------------
1       | 12                     
1       | 4                     
1       | 8     
2       | 23                    
2       | 45                    
2       | 7               
Run Code Online (Sandbox Code Playgroud)

我想要一个查询,每个返回一行user_id,但我想要的每个行user_id是每个amount最小user_id。所以我应该得到我的结果集:

-----------------
user_id | amount
-----------------                   
1       | 4                                        
2       | 7               
Run Code Online (Sandbox Code Playgroud)

DISTINCT在列上使用user_id可确保我不会得到重复的用户,但我不知道如何制作它,以便返回具有最少 amount用户行。

Gor*_*off 5

您可以使用distinct on

select distinct on (user) t.*
from t
order by user, amount;
Run Code Online (Sandbox Code Playgroud)

注意:如果您只想要最小的量,那么group by典型的解决方案是:

select user, min(amount)
from t
group by user;
Run Code Online (Sandbox Code Playgroud)

Distinct on是一种方便的 Postgres 扩展,可以轻松地为每组获取一行,而且它的性能通常比其他方法更好。


Use*_*ady 2

如果您的要求需要输出等于最小金额的行,例如表包含交易日期并且您在输出中需要它,那么一种方便的方法是使用row_number() over()选择所需的行。例如

CREATE TABLE mytable(
   user_id  INTEGER  NOT NULL
  ,amount   INTEGER  NOT NULL
  ,trandate DATE   NOT NULL
);
INSERT INTO mytable(user_id,amount,trandate) VALUES (1,12,'2020-09-12');
INSERT INTO mytable(user_id,amount,trandate) VALUES (1,4,'2020-10-02');
INSERT INTO mytable(user_id,amount,trandate) VALUES (1,8,'2020-11-12');
INSERT INTO mytable(user_id,amount,trandate) VALUES (2,23,'2020-12-02');
INSERT INTO mytable(user_id,amount,trandate) VALUES (2,45,'2021-01-12');
INSERT INTO mytable(user_id,amount,trandate) VALUES (2,7,'2021-02-02');

select
user_id, amount, trandate
from (
    select user_id, amount, trandate
        , row_number() over(partition by user_id order by amount) as rn
    from mytable
    ) t
where rn = 1
Run Code Online (Sandbox Code Playgroud)

结果:

+---------+--------+------------+
| user_id | amount |  trandate  |
+---------+--------+------------+
|       1 |      4 | 2020-10-02 |
|       2 |      7 | 2021-02-02 |
+---------+--------+------------+
Run Code Online (Sandbox Code Playgroud)

在 db<>fiddle处对此进行演示