在PostgreSQL中,我想一次获取每个用户并按日期排序。
这是我的疑问:
SELECT id, useridx, isread, message, date
FROM messages
WHERE isread = 1
GROUP BY useridx
ORDER BY date DESC
这是示例数据:
------------------------------------------------------
+ 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
------------------------------------------------------
现在,我想要做的是通过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
------------------------------------------------------
实际结果
ERROR: column "messages.date" must appear in the GROUP BY clause or be used in an aggregate function
我也不想将日期分组。我只想与useridx分组并按日期DESC对它们进行排序。
感谢任何帮助/想法!
注意:我也试过了Distinct。不适合我的需要或我做错了。
我在<{1}}和DISTINCT ON
方法之间非常困惑并且坚持。
结论: 对于谁在这里得到同样的问题可以读这个作为答案。 @ kgrittn和@mu都太短了,答案是正确的。我将继续在我的项目中使用答案和模式,并且我能够及时了解哪一个是最好的 - 猜测 - 。所以,选择其中一个继续你的工作。你会没事的。
上次更新:有时,Distinct On会从结果中排除某些ID。假设我有一个id列,我有6行是相同的。因此,不同于从结果中排除它BUT rank()只是结果它。 所以,请使用rank()!
答案 0 :(得分:10)
与MySQL不同,PostgreSQL不会显示未在聚合查询中聚合的列的随机数据。
解决方案在错误消息
中ERROR: column "messages.date" must appear in the GROUP BY clause or be used in an aggregate function
这意味着您必须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
答案 1 :(得分:7)
您希望使用rank()
window function在每个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
这会从您的示例中为您的行id
2,3和6提供。您可能希望在over
中添加辅助排序键,以便在同一日期每useridx
条有多封邮件时始终做出选择。
至少需要PostgreSQL 8.4(AFAIK)才能拥有窗口功能。
答案 2 :(得分:4)
另一种选择是使用SELECT DISTINCT ON
(这与简单的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;
在某些情况下,这可以比其他方法更好地扩展。
答案 3 :(得分:1)
您正在汇总结果。
这意味着用户3
不是2行,而是只有一行。但您也可以为聚合行选择id
,message
,isread
列。 PostgreSQL应该如何提供这些数据?应该是max()
可能的值吗?也许min()
?
我认为,您希望获得最新消息的数据。试试这个问题:
SELECT id, useridx, isread, message, date FROM messages
WHERE isread = 1 AND (useridx, date) IN
(SELECT useridx, max(date) FROM messages WHERE isread = 1 GROUP BY useridx);
答案 4 :(得分:1)
多年以后,但你不能只在FROM子查询中订购:
SELECT m.id, m.useridx, m.isread, m.message, m.date
FROM (
SELECT m2.id, m2.useridx, m2.isread, m2.message, m2.date
FROM message m2
ORDER BY m2.id ASC, m2.date DESC
) m
WHERE isread = 1
GROUP BY useridx
这适用于PostgreSQL 9.2