postgresql distinct on用法

除了我们熟知的distinct外,postgresql还支持distinct on,它的用途跟mysql没有启用ONLY_FULL_GROUP_BY SQL选项是一样的,针对声明的字段做分组,分组外的字段返回随机一行。如下:

lightdb@oradb=# create table t_distincton(id int,v text);
CREATE TABLE
lightdb@oradb=# 
lightdb@oradb=# 
lightdb@oradb=# insert into t_distincton values (1,'v1'),(2,'v2'),(3,'v3');
INSERT 0 3
lightdb@oradb=# insert into t_distincton values (1,'v1'),(2,'v2'),(3,'v4');
INSERT 0 3
lightdb@oradb=# select * from t_distincton ;
 id | v  
----+----
  1 | v1
  2 | v2
  3 | v3
  1 | v1
  2 | v2
  3 | v4
(6 rows)

lightdb@oradb=# select distinct on(id) v from t_distincton ;
 v  
----
 v1
 v2
 v3
(3 rows)

lightdb@oradb=# select distinct on(v) id,v from t_distincton ;
 id | v  
----+----
  1 | v1
  2 | v2
  3 | v3
  3 | v4
(4 rows)

lightdb@oradb=# select distinct on(v) id,v from t_distincton order by id;
ERROR:  SELECT DISTINCT ON expressions must match initial ORDER BY expressions
LINE 1: select distinct on(v) id,v from t_distincton order by id;
                           ^
lightdb@oradb=# select distinct on(v) id,v from t_distincton order by v,id;
 id | v  
----+----
  1 | v1
  2 | v2
  3 | v3
  3 | v4
(4 rows)

lightdb@oradb=# select distinct on(v,id) id,v from t_distincton order by v;
 id | v  
----+----
  1 | v1
  2 | v2
  3 | v3
  3 | v4
(4 rows)

如果不使用distinct on,也可以通过分析函数row_number()达到相同的效果,如下:

select from (select row_number() over (partition by a) as rn, * from t_distinct) t where rn=1; 

需要注意的是,如果有distinct on(a,b,c)的值有null,null被认为都相同,这个null != null不一样。

关于order by中不支持表达式的说明是SQL92的限制,可以参考https://postgrespro.com/list/thread-id/2097072。

posted @ 2024-01-10 09:56  zhjh256  阅读(118)  评论(0编辑  收藏  举报