Vis*_*seo 5 sql postgresql distinct sql-order-by greatest-n-per-group
我想打印一个人的最后一条消息,但每个人只应打印他的最新消息。我使用 PostgreSQL 10。
+-----------+----------+--------------+
| name | body | created_at |
+-----------+----------+--------------+
| Maria | Test3 | 2017-07-07 |
| Paul | Test5 | 2017-06-01 |
+-----------+----------+--------------+
Run Code Online (Sandbox Code Playgroud)
我已经用下面的 SQL 查询尝试过,这给了我确切的结果,但不幸的是,人们在其中加倍了。
+-----------+----------+--------------+
| name | body | created_at |
+-----------+----------+--------------+
| Maria | Test3 | 2017-07-07 |
| Paul | Test5 | 2017-06-01 |
+-----------+----------+--------------+
Run Code Online (Sandbox Code Playgroud)
+-----------+----------+--------------+
| name | body | created_at |
+-----------+----------+--------------+
| Maria | Test1 | 2016-06-01 |
| Maria | Test2 | 2016-11-01 |
| Maria | Test3 | 2017-07-07 |
| Paul | Test4 | 2017-01-01 |
| Paul | Test5 | 2017-06-01 |
+-----------+----------+--------------+
Run Code Online (Sandbox Code Playgroud)
我尝试使用 DISTINCT 删除重复项,但不幸的是我收到此错误消息:
SELECT * FROM messages
WHERE receive = 't'
GROUP BY name
ORDER BY MAX(created_at) DESC
Run Code Online (Sandbox Code Playgroud)
ERROR: SELECT DISTINCT ON expressions must match initial ORDER BY expressions LINE 1: SELECT DISTINCT ON (name) * FROM messages ^ : SELECT DISTINCT ON (name) * FROM messages WHERE receive = 't' GROUP BY name ORDER BY MAX(created_at) DESC
Run Code Online (Sandbox Code Playgroud)
您对我如何解决这个问题有什么想法吗?
您将使用DISTINCT ON如下:
SELECT DISTINCT ON (name) *
FROM messages
WHERE receive = 't'
ORDER BY name, created_at DESC
Run Code Online (Sandbox Code Playgroud)
那是:
GROUP BY不需要任何条款
中列出的列DISTINCT ON(...)必须出现在ORDER BY子句的前面
...后面是应该用来打破组的列(这里是created_at)
请注意,查询的结果distinct on始终按子句中的列排序(因为这种排序用于标识应保留哪些行)。
如果您想更好地控制排序顺序,则可以使用窗口函数:
SELECT *
FROM (
SELECT m.*, ROW_NUMBER() OVER(PARTITION BY name ORDER BY created_at DESC) rn
FROM messages m
WHERE receive = 't'
) t
WHERE rn = 1
ORDER BY created_at DESC
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4369 次 |
| 最近记录: |