代码改变世界

PostgreSQL DISTINCT 和 DISTINCT ON

  abce  阅读(3994)  评论(0编辑  收藏  举报

select语句中,使用distinct关键字,在处理select list后,结果表可以选择消除重复的行。在SELECT之后直接写入DISTINCT关键字以指定此关键字:

1
SELECT DISTINCT select_list ...

(可以使用关键字ALL代替DISTINCT来指定保留所有行的默认行为)

 

显然,如果两行至少有一个列值不同,则认为它们是不同的。在此比较中,将空值视为相等。

 

另外,一个任意表达式可以确定哪些行被认为是不同的:

1
SELECT DISTINCT ON (expression [, expression ...]) select_list ...

这里的expression是一个针对所有行求值的任意值表达式。 一组所有表达式均相等的行被视为重复行,并且仅该集合的第一行保留在输出中。请注意,除非查询在足够的列上排序以保证到达DISTINCT过滤器的行的唯一顺序,否则集合的“第一行”是不可预测的。(DISTINCT ON处理在ORDER BY排序之后进行)

DISTINCT ON子句不是SQL标准的一部分,有时由于其结果的不确定性而有时被认为是不良样式。通过明智地使用GROUP BYFROM中的子查询,可以避免这种构造,但是它通常是最方便的选择。

 

1
2
3
4
5
6
7
8
9
10
11
12
create table t_distinct(a int ,b int ,c int);
insert into t_distinct values(1,2,3);
insert into t_distinct values(2,3,4);
insert into t_distinct values(3,4,5);
 
insert into t_distinct values(2,2,3);
insert into t_distinct values(3,3,4);
insert into t_distinct values(4,4,5);
 
insert into t_distinct(a,b) values(5,6);
insert into t_distinct(a,b) values(5,6);
insert into t_distinct(a,b) values(6,7);

  

1.返回所有记录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# select a,b,c from t_distinct;
 a | b | c
---+---+---
 1 | 2 | 3
 2 | 3 | 4
 3 | 4 | 5
 2 | 2 | 3
 3 | 3 | 4
 4 | 4 | 5
 5 | 6 | 
 5 | 6 | 
 6 | 7 | 
(9 rows)
 
# select all a,b,c from t_distinct;
 a | b | c
---+---+---
 1 | 2 | 3
 2 | 3 | 4
 3 | 4 | 5
 2 | 2 | 3
 3 | 3 | 4
 4 | 4 | 5
 5 | 6 | 
 5 | 6 | 
 6 | 7 | 
(9 rows)

  

2.返回 a,b,c 唯一值。(这里NULL视为相等)

1
2
3
4
5
6
7
8
9
10
11
12
# select distinct a,b,c from t_distinct;
 a | b | c
---+---+---
 2 | 2 | 3
 5 | 6 | 
 1 | 2 | 3
 6 | 7 | 
 3 | 3 | 4
 4 | 4 | 5
 3 | 4 | 5
 2 | 3 | 4
(8 rows)

  

3.返回a唯一的任意行

1
2
3
4
5
6
7
8
9
10
# select distinct on (a) a,b,c from t_distinct;
 a | b | c
---+---+---
 1 | 2 | 3
 2 | 2 | 3
 3 | 3 | 4
 4 | 4 | 5
 5 | 6 | 
 6 | 7 | 
(6 rows)

使用窗口函数可以达到类似效果,但是可以确定返回哪行,因此也更慢一些:

1
2
3
4
5
6
7
8
9
10
# select * from (select row_number() over (partition by a) as rn, * from t_distinct) t where rn=1; 
 rn | a | b | c
----+---+---+---
  1 | 1 | 2 | 3
  1 | 2 | 2 | 3
  1 | 3 | 3 | 4
  1 | 4 | 4 | 5
  1 | 5 | 6 | 
  1 | 6 | 7 | 
(6 rows)

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# select distinct on (a,b) a,b,c from t_distinct;
 a | b | c
---+---+---
 1 | 2 | 3
 2 | 2 | 3
 2 | 3 | 4
 3 | 3 | 4
 3 | 4 | 5
 4 | 4 | 5
 5 | 6 | 
 6 | 7 | 
(8 rows)
 
 
#这里NULL视为相等
# select distinct on (c) a,b,c from t_distinct;
 a | b | c
---+---+---
 1 | 2 | 3
 3 | 3 | 4
 3 | 4 | 5
 5 | 6 | 
(4 rows)

  

编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
历史上的今天:
2015-10-22 Symantec Backup Exec(BE)的启停
2015-10-22 卸载linux订阅包
点击右上角即可分享
微信分享提示