【问题标题】:RoR PostgresQL - Get latest, distinct values from databaseRoR PostgresQL - 从数据库中获取最新的不同值
【发布时间】:2018-02-09 14:01:01
【问题描述】:

我正在尝试查询我的 PostgreSQL 数据库以获取最新的(通过 created_at)和不同的(通过 user_id)活动对象,其中每个用户在数据库中都有多个活动。活动对象的结构如下:

Activity(id, user_id, created_at, ...)

我首先尝试让以下查询工作:

Activity.order('created_at DESC').select('DISTINCT ON (activities.user_id) activities.*')

但是,不断收到以下错误:

ActiveRecord::StatementInvalid: PG::InvalidColumnReference: ERROR:  SELECT DISTINCT ON expressions must match initial ORDER BY expressions

根据这篇文章:PG::Error: SELECT DISTINCT, ORDER BY expressions must appear in select list,看起来 ORDER BY 子句只能在应用了 DISTINCT 之后才能应用。这对我没有帮助,因为我想通过 user_id 获得不同的活动,但也希望这些活动是最近创建的活动。因此,我需要在获得不同的活动之前对活动进行排序。

我提出了一个可行的解决方案,但首先按用户 ID 对活动进行分组,然后按 created_at 对组内的活动进行排序。但是,这需要执行两个查询。

我想知道我想要的是否仅在一个查询中就可以实现?

【问题讨论】:

  • 如果你在 distinct 之后排序,你仍然会得到最近创建的活动。

标签: ruby-on-rails postgresql


【解决方案1】:

这应该可以,试试下面的

解决方案 1

Activity.select('DISTINCT ON (activities.user_id) activities.*').order('created_at DESC')

解决方案 2

如果不起作用解决方案 1,那么如果您为此创建范围,这将很有帮助

activity型号

scope :latest, -> {
                    select("distinct on(user_id) activities.user_id,
                                activities.*").
                    order("user_id, created_at desc")
                }

现在你可以像下面这样在任何地方调用它

Activity.latest

希望对你有帮助

【讨论】:

  • @MarcusChristiansen 让我们试试解决方案
  • 嗨@fool-dev,这似乎有效!谢谢!如果你有时间,你能快速解释一下这是如何工作的吗?如果我排除 order 子句,我不会得到最新的,但如果我包含它,我会得到最新的。这看起来很奇怪,因为 order 子句似乎正在更改 sql 查询的内容,而不是对现有内容进行排序。
  • @MarcusChristiansen 这是DISTINCT ON 的一个功能:它只为给定表达式的每个不同值选择 first 记录(无论是单个值,如此处所做的,或者一个元组,如果你指定了多个)。 DISTINCT ON 的使用要求结果首先按相同的表达式排序,但随后的排序定义了哪些记录将首先出现并进入结果集。 Postgres 的文档很好地解释了这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-21
  • 2014-05-23
  • 2010-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多