【问题标题】:Most recent inner query in activerecordactiverecord 中的最新内部查询
【发布时间】:2020-09-14 18:19:56
【问题描述】:

我有一张桌子users

id  first_name
--------------
1   Bill
2   Denise

谁读过多个books

id  book                       user_id  read_at
---------------------------------------------------
1   Garry Potter               1        2020-1-1
2   Lord of the wrist watch    2        2020-1-1
3   90 Shades of navy          2        2020-1-2

我想在我的 book 模型中创建一个范围,为每个用户获取最新的书籍。有很多使用纯 SQL 执行此操作的示例,我遇到的问题是创建一个灵活的范围,该范围可以与计数、内部查询或您通常使用范围的任何其他方式一起使用。

到目前为止,我的 book 模型中有这个:

def self.most_recent
  inner_query = select('DISTINCT ON (user_id) *').order(:user_id, read_at: :desc)
  select('*').from(inner_query, :inner_query).order('inner_query.id')
end

这与我想要的非常接近。它适用于计数,但不适用于更复杂的情况。

例如,如果我想获取他们最新一本书是“Garry Potter”的用户列表,我会尝试这样的操作:

User.where(id: Book.most_recent.where(book: 'Garry Potter').select(:user_id))

活动记录被混淆并生成以下 SQL:

SELECT "users".* FROM "users" WHERE "users"."id" IN (SELECT "user_id", * FROM (SELECT "books"."user_id", DISTINCT ON (user_id) * FROM "books" ORDER BY "books"."user_id" ASC, "books"."read_at" DESC) inner_query WHERE "books"."book" = "Garry Potter" ORDER BY inner_query.id)

这给出了以下错误:

ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR:  syntax error at or near "DISTINCT"

有没有优雅的方法来实现这一点?

【问题讨论】:

    标签: sql ruby-on-rails postgresql activerecord distinct-on


    【解决方案1】:

    您可以尝试通过返回带有where 的查询来更改方法most_recent

    def self.most_recent
      # Select only the ids of the most recent books
      inner_query = select('DISTINCT ON (user_id) books.id').order(:user_id, read_at: :desc)
    
      # Return a where query like Book.where(id: <ids in the result set of the query above>)
      where(id: inner_query)
    end
    
    # You should now be able to perform the following query
    User.where(
      id: Book.most_recent.where(book: 'Garry Potter').select(:user_id)
    )
    

    【讨论】:

    • 比我的优雅得多,但仍然有同样的 Rails 问题是将 "books"."user_id" 插入 inner_query 选择语句导致语法无效 - SELECT "users".* FROM "users" WHERE "users"."id" IN (SELECT "books"."user_id" FROM "books" WHERE "books"."id" IN (SELECT "books"."user_id", DISTINCT ON (user_id) books.id FROM "books" ORDER BY "books"."user_id" ASC, "books"."read_at" DESC))
    • 我使用的是 rails 5.2.4.3,是否是 rails 错误没有正确处理 DISTINCT ON 的双嵌套查询?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多