我需要查询数据库并检索最近10个活动或拒绝的对象。我们使用以下内容:
User.where(status: [:active, :declined]).limit(10)
现在我们需要获得每个状态的最后10个(总共20个用户)
我尝试了以下内容:
User.where(status: :active).limit(10).or(User.where(status: : declined).limit(10))
# SELECT "users".* FROM "users" WHERE ("users"."status" = $1 OR "users"."status" = $2) LIMIT $3
这与上一个查询相同,只返回10个混合状态的用户。
如何使用单个查询获取最近10位活跃用户和最后10位拒绝用户?
答案 0 :(得分:1)
我不确定SQL是否允许执行您想要的操作。我会尝试的第一件事是使用子查询,如下所示:
class User < ApplicationRecord
scope :active, -> { where status: :active }
scope :declined, -> { where status: :declined }
scope :last_active_or_declined, -> {
where(id: active.limit(10).pluck(:id))
.or(where(id: declined.limit(10).pluck(:id))
}
end
然后你可以做的其他地方
User.last_active_or_declined()
这样做是为了执行2个不同的子查询,分别询问每个用户组,然后获取propper组ID中的那些用户。我会说你甚至可以忘记pluck(:id)
部分,因为ActiveRecord非常聪明,可以为select
添加正确的SQL
条款,但我不是百分百肯定而且我不喜欢我手头有任何Rails项目,我可以尝试这个。
答案 1 :(得分:0)
limit
不是#or
关系的允许值。如果您检查Rails代码,则引发的错误来自here:
def or!(other) # :nodoc:
incompatible_values = structurally_incompatible_values_for_or(other)
unless incompatible_values.empty?
raise ArgumentError, "Relation passed to #or must be structurally compatible. Incompatible values: #{incompatible_values}"
end
# more code
end
您可以在代码here中检查哪些方法受到进一步限制:
STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having, :unscope, :references]
def structurally_incompatible_values_for_or(other)
STRUCTURAL_OR_METHODS.reject do |method|
get_value(method) == other.get_value(method)
end
end
您可以在Relation
课程here中看到限制受限:
SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :reordering,
:reverse_order, :distinct, :create_with, :skip_query_cache,
:skip_preloading]
所以你不得不诉诸原始SQL我害怕
答案 2 :(得分:0)
我认为您无法使用单个查询来执行此操作,但您可以使用两个查询来执行此操作,获取记录ID,然后使用这些记录ID构建查询。
这并不理想,但由于你只是采摘ids,影响并不是太糟糕。
user_ids = User.where(status: :active).limit(10).pluck(:id) + User.where(status: :declined).limit(10).pluck(id)
users = User.where(id: user_ids)
答案 3 :(得分:0)
我认为您可以使用UNION
。安装active_record_union并将or
替换为union
:
User.where(status: :active).limit(10).union(User.where(status: :declined).limit(10))