为每个用户选择最新条目而不使用 group by (postgres)

Posted

技术标签:

【中文标题】为每个用户选择最新条目而不使用 group by (postgres)【英文标题】:Select newest entry for each user without using group by (postgres) 【发布时间】:2020-11-19 04:09:48 【问题描述】:

我有一张表myTable,有四列:

id        UUID,
user_id   UUID ,
text      VARCHAR ,
date      TIMESTAMP

id 是主键,user_id 在此表中不是唯一的)

我想检索按其最新条目排序的user_ids,我目前正在使用此查询:

SELECT user_id FROM myTable GROUP BY user_id ORDER BY MAX(date) DESC

问题是GROUP BY 需要很长时间。有没有更快的方法来实现这一点?我尝试使用带有PARTITION BY 的窗口函数,如此处所述Retrieving the last record in each group - mysql,但它并没有真正加快速度。我还确保 user_id 已编入索引。

我的 postgres 版本是 10.4

编辑:我当前使用的上述查询在功能上是正确的,问题是它很慢。

【问题讨论】:

“按最新条目排序”是什么意思?您想查看最新条目(您的标题所暗示的内容)还是全部,但使用某种特殊的排序顺序? 我想要 all user_ids,按每个 user_id 的最新日期排序。上面的查询是正确的,只是速度很慢。我不是在寻找完整的条目,只有 user_ids。 那你为什么不能简单地使用select user_id from the_table order by user_id, "date" desc 也许我解释得不好,我想要所有的 user_id,但每个 user_id 只需要一次。 【参考方案1】:

您的查询似乎是满足您要求的相关方法:

select user_id 
from mytable 
group by user_id 
order by max(date) desc

我建议在(user, date desc) 上建立索引以加快速度。它必须是两个列上的单个索引。

您也可以尝试distinct on,这可能或可能不会为您提供更好的性能:

select user_id
from (
    select distinct on(user_id) user_id, date
    from mytable
    order by user_id, date desc
) t
order by date desc

【讨论】:

索引应该在(user_id, date DESC) @VesaKarjalainen:啊,是的,显然……谢谢。 我最终喜欢上了这个 PostgreSQL SQL 扩展。非常方便。 @GMB 现在,当然,我希望能够为每组保留不止一行。也许像distinct (5) on (user_id) 这样的东西?我知道我知道。我现在要求太多了:D @TheImpaler: 不,distinct on 不能那样做...在这种情况下,您需要采用古老的 row_number() 方法。【参考方案2】:

user_id, date desc 上的索引开始。这可能会有所帮助。

你也可以尝试过滤——一旦你有了这样的索引:

select t.user_id
from myTable t
where t.date = (select max(t2.date)
                from myTable t2
                where t2.user_id = t.user_id
               )
order by t.date desc

但是,您可能会发现 order by 最终花费的时间几乎与 group by 一样多。

这个版本肯定会为子查询使用索引:

select user_id
from (select distinct on (user_id) user_id, date
      from myTable t
      order by user_id, date desc
     ) t
order by date desc;

【讨论】:

添加索引加快了速度:)。此外,您的两个建议都比我当前的查询更快,尽管第一种方法给出了一些重复,大概是因为一些 user_ids 有多个具有相同最新日期的条目。

以上是关于为每个用户选择最新条目而不使用 group by (postgres)的主要内容,如果未能解决你的问题,请参考以下文章

优化 GROUP BY 查询以检索每个用户的最新行

GROUP BY最新用户,但最新日期没有用户

选择描述字段而不将其包含在 GROUP BY 子句中时 GROUP BY id 的最佳方法

在 sqlalchemy 中使用 distinct()/group_by() 获取基于每个“名称”列的最新记录

MySQL GROUP BY 返回第一项 - 需要选择最后一项

使用 group by 和条件优化 SQL 查询