我来自MySQL背景,其中GROUP BY与Postgres的工作方式截然不同。在Postgres中 - 显然是任何基于标准的SQL数据库 - 你必须按所有选定的列进行分组,而在MySQL中你可以手工挑选哪些列进行分组。
我读到你可以获得与DISTINCT ON
相同的效果,而且大多数情况都是如此。问题是你必须ORDER BY
所有不同的列,这个排序必须是最左边的排序。当我想主要通过另一个专栏订购时,这是一个问题。
现在我的查询如下:
SELECT
DISTINCT ON (eventable_id, eventable_type)
events.eventable_id, events.eventable_type, events.*
FROM events
WHERE <query>
ORDER BY eventable_id, eventable_type, events.created_at DESC
我想换掉订单,看起来像这样:
ORDER BY events.created_at, eventable_id, eventable_type DESC
有任何关于让它发挥作用的建议吗?
答案 0 :(得分:4)
由于您选择的是events.*
,因此不应将eventable_id
和eventable_type
冗余地添加到输出列。会导致重复的列名称。您知道您不必在目标列表的DISTINCT ON
子句中包含列,对吧?
此外,立即使用eventable_type DESC
可能会更快,因为您的最终排序顺序是这样的。这也是允许的。
SELECT DISTINCT ON (eventable_id, eventable_type)
*
FROM events
WHERE <condition>
ORDER BY eventable_id, eventable_type DESC, created_at DESC
@Denis已经涵盖了其余部分:在外部查询中将其作为子查询并按顺序排序。
替代将是GROUP BY
和max()
的子选择,但是当每个组的最新created_at
不唯一时,每个组会产生多个列。 (可能或可能不合适。)并且它可能仍然比DISTINCT ON
更慢,但需要额外的ORDER BY
步骤。使用EXPLAIN ANALYZE
进行测试。
SELECT e.*
FROM events e
JOIN (
SELECT eventable_id, eventable_type, max(created_at) AS created_at
FROM events
WHERE <condition>
GROUP BY 1, 2 DESC
) sub USING (eventable_id, eventable_type, created_at) -- maybe not unique
WHERE <repeat condition if dupes may be eliminated>
ORDER BY e.created_at, e.eventable_id, e.eventable_type DESC
答案 1 :(得分:1)
如果Postgres抱怨,请使用子选择:
select * from ( ... ) q order by ...
(如果确实如此,我会把它作为查询计划会吮吸的暗示。)