ist*_*tan 31 ruby sql ruby-on-rails
class User
has_many :books
Run Code Online (Sandbox Code Playgroud)
我需要一个返回的查询:
最近一本书的用户:complete => true.即如果用户最近的书有:complete => false,我不希望它们出现在我的结果中.
到目前为止我有什么
User.joins(:books).merge(Book.where(:complete => true))
Run Code Online (Sandbox Code Playgroud)
这是一个很有希望的开始,但没有给我我需要的结果.我已经尝试.order("created_on desc").limit(1)
在上面的查询结尾处添加一个但是当我期待很多时,我最终只得到一个结果.
谢谢!
Pan*_*kos 47
如果您不打算使用@ rubyprince的ruby解决方案,这实际上是一个比ActiveRecord可以处理的最复杂的数据库查询,因为它需要一个子查询.以下是我将如何使用查询完成此操作:
SELECT users.*
FROM users
INNER JOIN books on books.user_id = users.id
WHERE books.created_on = ( SELECT MAX(books.created_on)
FROM books
WHERE books.user_id = users.id)
AND books.complete = true
GROUP BY users.id
Run Code Online (Sandbox Code Playgroud)
要将其转换为ActiveRecord,我将执行以下操作:
class User
scope :last_book_completed, joins(:books)
.where('books.created_on = (SELECT MAX(books.created_on) FROM books WHERE books.user_id = users.id)')
.where('books.complete = true')
.group('users.id')
end
Run Code Online (Sandbox Code Playgroud)
然后,您可以通过执行以下操作获取具有上次完成的书籍的所有用户的列表:
User.last_book_completed
Run Code Online (Sandbox Code Playgroud)
Mar*_*rom 14
这增加了一点开销,但是在重要时节省了复杂性并提高了速度.
在书籍中添加"most_recent"列.确保添加索引.
class AddMostRecentToBooks < ActiveRecord::Migration
def self.change
add_column :books, :most_recent, :boolean, :default => false, :null => false
end
add_index :books, :most_recent, where: :most_recent # partial index
end
Run Code Online (Sandbox Code Playgroud)
然后,当您保存书籍时,请更新most_recent
class Book < ActiveRecord::Base
on_save :mark_most_recent
def mark_most_recent
user.books.order(:created_at => :desc).offset(1).update_all(:most_recent => false)
user.books.order(:created_at => :desc).limit(1).update_all(:most_recent => true)
end
end
Run Code Online (Sandbox Code Playgroud)
现在,为您的查询
class User < ActiveRecord::Base
# Could also include and preload most-recent book this way for lists if you wanted
has_one :most_recent_book, -> { where(:most_recent => true) }, :class_name => 'Book'
scope :last_book_completed, -> { joins(:books).where(:books => { :most_recent => true, :complete => true })
end
Run Code Online (Sandbox Code Playgroud)
这允许您像这样编写它,结果是一个与其他范围一起使用的Relation.
User.last_book_completed
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
18557 次 |
| 最近记录: |