flo*_*r58 16 postgresql group-by distinct distinct-on
在PostgreSQL中,我想一次获取每个用户并按日期排序.
这是我的查询:
SELECT id, useridx, isread, message, date
FROM messages
WHERE isread = 1
GROUP BY useridx
ORDER BY date DESC
Run Code Online (Sandbox Code Playgroud)
这是一个示例数据:
------------------------------------------------------
+ id | useridx | isread | messsage | date +
------------------------------------------------------
1 | 1 | 0 | Hello | 2012-01-01
2 | 2 | 1 | Hi | 2012-01-02
3 | 3 | 1 | Test | 2012-01-03
4 | 3 | 0 | My Msg | 2012-01-04
5 | 4 | 1 | sadasd | 2012-01-05
6 | 4 | 1 | sdfsdfd | 2012-01-06
7 | 4 | 0 | sdfsdfsd | 2012-01-07
8 | 5 | 0 | 5345634 | 2012-01-08
9 | 6 | 0 | sdfdfsd | 2012-01-09
10 | 7 | 0 | sdfsdfsf | 2012-01-10
------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
现在,我想要做的是通过useridx和按日期排序来获取此表.
预期成果:
------------------------------------------------------
+ id | useridx | isread | messsage | date +
------------------------------------------------------
6 | 4 | 1 | sdfsdfd | 2012-01-06
3 | 3 | 1 | Test | 2012-01-03
2 | 2 | 1 | Hi | 2012-01-02
------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
实际结果
ERROR: column "messages.date" must appear in the GROUP BY clause or be used in an aggregate function
Run Code Online (Sandbox Code Playgroud)
我也不想把日期分组.我只想与useridx分组并按日期DESC对它们进行排序.
任何帮助/想法表示赞赏!
注意:我也尝试过Distinct.不适合我的需要或我做错了.
我非常困惑和困在DISTINCT ON和rank()方法之间.
结论:对于谁在这里遇到同样的问题,可以将其作为答案.@ kgrittn和@mu都太短了,答案是正确的.我将继续在我的项目中使用答案和模式,并且我能够及时了解哪一个是最好的 - 猜测 - .所以,选择其中一个继续你的工作.你会没事的.
最后更新:有时,Distinct On会从结果中排除某些ID.假设我有一个id列,我有6行是相同的.因此,不同于从结果中排除它BUT rank()只是结果它.所以,使用rank()!
ila*_*nco 10
与MySQL不同,PostgreSQL不会显示未在聚合查询中聚合的列的随机数据.
有关更长的解释和更多示例:http://practiceovertheory.com/blog/2009/09/23/postgresql-s-group-by/
解决方案在错误消息中
ERROR: column "messages.date" must appear in the GROUP BY clause or be used in an aggregate function
Run Code Online (Sandbox Code Playgroud)
这意味着您必须GROUPDU"messages.date"列或在选择此列时使用MIN()或MAX()等聚合函数
例:
SELECT MIN(id), useridx, isread, message, MAX(date)
FROM messages WHERE isread = 1
GROUP BY useridx, isread, message
ORDER BY MAX(date) DESC
Run Code Online (Sandbox Code Playgroud)
您希望使用rank()窗口函数在每个useridx组中对结果进行排序,然后通过将排序结果包装在派生表中来剥离第一个结果:
select id, useridx, isread, message, date
from (
select id, useridx, isread, message, date,
rank() over (partition by useridx order by date desc) as r
from messages
where isread = 1
) as dt
where r = 1
Run Code Online (Sandbox Code Playgroud)
这将为id您的样本中的行提供2,3和6 行.您可能希望在over每个useridx同一日期有多封邮件时在其中添加辅助排序键以始终如一地进行选择.
你至少需要PostgreSQL 8.4(AFAIK)才能拥有窗口功能.
另一种选择是使用SELECT DISTINCT ON(这与 simple 非常不同SELECT DISTINCT):
SELECT *
FROM (SELECT DISTINCT ON (useridx)
id, useridx, isread, message, date
FROM messages
WHERE isread = 1
ORDER BY useridx, date DESC) x
ORDER BY date DESC;
Run Code Online (Sandbox Code Playgroud)
在某些情况下,这可以比其他方法更好地扩展。
| 归档时间: |
|
| 查看次数: |
18458 次 |
| 最近记录: |