postgre dinstinct on()的使用

时间:2024-01-01 10:12:03
意思是DISTINCT ON ( expression [, …] )把记录根据[, …]的值进行分组,分组之后仅返回每一组的第一行。
需要注意的是,如果你不指定ORDER BY子句,返回的第一条的不确定的。如果你使用了ORDER BY 子句,
那么[, …]里面的值必须靠近ORDER BY子句的最左边。
postgres=# CREATE TABLE score_ranking (id int, name text, subject text, score numeric);

postgres=# INSERT INTO score_ranking VALUES (1,'killerbee','数学',99.5), (2,'killerbee','语文',89.5),(3,'killerbee','英语',79.5), (4,'killerbee','物理',99.5), (5,'killerbee','化学',98.5),(6,'刘德华','数学',89.5), (7,'刘德华','语文',99.5), (8,'刘德华','英语',79.5),(9,'刘德华','物理',89.5), (10,'刘德华','化学',69.5),(11,'张学友','数学',89.5), (12,'张学友','语文',91.5), (13,'张学友','英语',92.5),(14,'张学友','物理',93.5), (15,'张学友','化学',94.5);
//先查看下当前表的内容。
postgres=# select * from score_ranking ;
id | name | subject | score
----+-----------+---------+-------
1 | killerbee | 数学 | 99.5
2 | killerbee | 语文 | 89.5
3 | killerbee | 英语 | 79.5
4 | killerbee | 物理 | 99.5
5 | killerbee | 化学 | 98.5
6 | 刘德华 | 数学 | 89.5
7 | 刘德华 | 语文 | 99.5
8 | 刘德华 | 英语 | 79.5
9 | 刘德华 | 物理 | 89.5
10 | 刘德华 | 化学 | 69.5
11 | 张学友 | 数学 | 89.5
12 | 张学友 | 语文 | 91.5
13 | 张学友 | 英语 | 92.5
14 | 张学友 | 物理 | 93.5
15 | 张学友 | 化学 | 94.5
(15 rows) //以下就是 distict on 的用法:
//取出每门课程的第一名.
postgres=# select distinct on (subject) id,name,subject,score
from score_ranking
order by subject,score desc; 备注:逻辑是: 先依据subject进行分组,比如如果subject有五类,那就分成5组。其次,score desc决定每一组内部排序,最终决定每组取谁。 id | name | subject | score
----+-----------+---------+-------
5 | killerbee | 化学 | 98.5
1 | killerbee | 数学 | 99.5
4 | killerbee | 物理 | 99.5
13 | 张学友 | 英语 | 92.5
7 | 刘德华 | 语文 | 99.5
(5 rows)

order by的时候,按照上面的说法

"如果你使用了ORDER BY 子句, 那么[, …]里面的值必须靠近ORDER BY子句的最左边。"
select distinct on (subject),所以根据分数排序的时候,本来应该是order by score,而[, …]里面的值(subject)必须靠近ORDER BY子句的最左边,
所以是 order by subject,score desc;