我用Ruby on Rail的查询接口写了几个复杂的查询(至少对我来说):
watched_news_posts = Post.joins(:news => :watched).where(:watched => {:user_id => id})
watched_topic_posts = Post.joins(:post_topic_relationships => {:topic => :watched}).where(:watched => {:user_id => id})
Run Code Online (Sandbox Code Playgroud)
这两个查询都可以自行完成.两者都返回Post对象.我想将这些帖子合并到一个ActiveRelation中.由于某些时候可能有数十万个帖子,因此需要在数据库级别完成.如果是MySQL查询,我可以简单地使用UNION运算符.有没有人知道我是否可以用RoR的查询界面做类似的事情?
在Rails中使用Arel - 我正在寻找一种创建ActiveRecord::Relation有效结果的方法SELECT * FROM table,我仍然可以进一步操作.
例如,我有一个分为多个类别的模型,我按以下方式返回这些类型的计数:
relation = Model.where(:archived => false) # all non-archived records
record_counts = {
:total => relation.count,
:for_sale => relation.where(:for_sale => true).count
:on_auction => relation.where(:on_auction => true).count
}
Run Code Online (Sandbox Code Playgroud)
这样可以正常工作,并且具有COUNT向MySQL发送查询的优势,而不是实际选择记录本身.
但是,我现在需要在计数中包含存档记录,但relation = Model.all结果是Array,我正在寻找ActiveRecord::Relation.
我能想到这样做的唯一方法是model.where(model.arel_table[:id].not_eq(nil)),这有效,但似乎有些荒谬.
任何人都可以对此有所了解吗?
我想执行一个ActiveRecord查询,该查询返回除具有某些id的记录之外的所有记录.我想要排除的ID存储在一个数组中.所以:
ids_to_exclude = [1,2,3]
array_without_excluded_ids = Item. ???
Run Code Online (Sandbox Code Playgroud)
我不知道如何完成第二行.
背景:我已经尝试过的:
我不确定背景是否必要,但我已经尝试过.find和.where的各种组合.例如:
array_without_excluded_ids = Item.find(:all, :conditions => { "id not IN (?)", ids_to_exclude })
array_without_excluded_ids = Item.where( "items.id not IN ?", ids_to_exclude)
Run Code Online (Sandbox Code Playgroud)
这些失败了. 这个提示可能在正确的轨道上,但我没有成功地适应它.任何帮助将不胜感激.
这与一年前的一个问题有关.
我提出了一个开箱即用的问题示例,只要你有sqlite3可用:https://github.com/cairo140/rails-eager-loading-counts-demo
git clone git://github.com/cairo140/rails-eager-loading-counts-demo.git
cd rails-eager-loading-counts-demo
rails s
Run Code Online (Sandbox Code Playgroud)
我在存储库中有更全面的文章,但我的一般问题是这个.
如何以最小化数据库查询的方式使Rails急切加载计数?
尽管在ActiveRelation 中包含了该关联,但n+1只要您#count在关联上使用该问题就会出现问题#includes(:associated).一种解决方法是使用#length,但只有当它被调用的对象已被加载时才能正常工作,更不用说我怀疑它复制了Rails内部已经完成的东西.此外,使用的一个问题#length是,当开始时没有加载关联时,它会导致不幸的过载,并且只需要计数.
从自述文件:
我们可以通过在posts数组上运行#length来解决这个问题(参见附录),这已经加载了,但是也可以随时使用.它不仅更加一致; 它提供了一个访问路径,不一定需要加载帖子.例如,如果你有一个部分显示计数,无论什么,但一半的时间,部分是在加载帖子和一半时间没有调用,你面临以下情况:
- 运用
#count
- n
COUNT已经加载帖子时的样式查询- n
COUNT尚未加载帖子时的样式查询- 运用
#length
- 在已加载帖子时将其他查询归零
- n
*尚未加载帖子时的样式查询在这两种选择之间,没有主导选择.但是修改#count来推迟#length或访问存储在幕后的其他方式的长度会很好,这样我们就可以得到以下场景:
- 使用修改
#count
- 在已加载帖子时将其他查询归零
- n
COUNT尚未加载帖子时的样式查询
那么这里的正确方法是什么?有没有我忽略的东西(非常非常可能)?
我需要能够UNION使用ActiveRelation 链接任意数量的子选择.
我对ARel的实现有点困惑,因为它似乎假设UNION是二进制操作.
然而:
( select_statement_a ) UNION ( select_statement_b ) UNION ( select_statement_c )
Run Code Online (Sandbox Code Playgroud)
是有效的SQL.如果不做令人讨厌的字符串替换,这可能吗?
例
class User
has_many :tickets
end
Run Code Online (Sandbox Code Playgroud)
我想创建包含用户计数票据逻辑的关联,并在包含中使用它(用户has_one ticket_count)
Users.includes(:tickets_count)
Run Code Online (Sandbox Code Playgroud)
我试过了
has_one :tickets_count, :select => "COUNT(*) as tickets_count,tickets.user_id " ,:class_name => 'Ticket', :group => "tickets.user_id", :readonly => true
User.includes(:tickets_count)
ArgumentError: Unknown key: group
Run Code Online (Sandbox Code Playgroud)
在这种情况下,include中的关联查询应该使用count with group by ...如何使用rails实现这一点?
更新
UPDATE2
我知道SQL,我知道如何用连接选择它,但我的问题现在就像"如何获取数据".我的问题是关于建立我可以在包含中使用的关联.谢谢
Update3 我尝试创建像用户has_one ticket_count创建的关联,但是
ruby activerecord ruby-on-rails active-relation ruby-on-rails-3
首先,我得到特定日期之间的审核状态.
date_range = Date.parse(@from_date).beginning_of_day..Date.parse(@to_date).end_of_day
@review_statuses = ReviewStatus.where(updated_at: date_range)
Run Code Online (Sandbox Code Playgroud)
接下来,我需要应用'AND'条件.
@review_cycle = params[:review_cycle]
if @review_cycle.present?
@review_statuses = @review_statuses.merge(
ReviewStatus.where(evidence_cycle: @review_cycle)
.or(ReviewStatus.where(roc_cycle: @review_cycle)))
end
Run Code Online (Sandbox Code Playgroud)
现在,对于下面我应该应用'where'或'merge'.
@status = params[:status]
@review_statuses.where(evidence_status: :pass, roc_status: :pass) if @status == 'pass'
Run Code Online (Sandbox Code Playgroud)
有人可以解释,我们何时应该使用merge而不是where?
我有这样的代码:
t = "%#{term}%"
where('name like ? or email like ? or postcode like ?', t, t, t)
Run Code Online (Sandbox Code Playgroud)
正如您所看到的那样,它正在跨多个领域进行搜索.
有没有办法避免重复的t?这让我觉得很脏.
谢谢
如何将以下SQL查询转换为ActiveRecord关系,以便我可以使用范围扩展它?
WITH joined_table AS (
SELECT workout_sets.weight AS weight,
workouts.user_id AS user_id,
workouts.id AS workout_id,
workout_sets.id AS workout_set_id,
workout_exercises.exercise_id AS exercise_id
FROM workouts
INNER JOIN workout_exercises ON workout_exercises.workout_id = workouts.id
INNER JOIN workout_sets ON workout_sets.workout_exercise_id = workout_exercises.id
ORDER BY workout_sets.weight DESC
),
sub_query AS (
SELECT p.user_id, MAX(weight) as weight
FROM joined_table p
GROUP BY p.user_id
),
result_set AS (
SELECT MAX(x.workout_id) AS workout_id, x.user_id, x.weight, x.workout_set_id, x.exercise_id
FROM joined_table x
JOIN sub_query y
ON y.user_id = x.user_id AND y.weight …Run Code Online (Sandbox Code Playgroud) sql activerecord ruby-on-rails active-relation ruby-on-rails-4
我查看了Arel源代码,以及Rails 3.0的一些activerecord源代码,但我似乎无法为自己收集一个很好的答案,因为在构造查询时Arel是否会改变我们使用includes()的能力, 为了更好.
有些情况下,人们可能想要修改activerecord上的条件:包括2.3.5及之前的查询,用于返回的关联记录.但据我所知,这对于所有人来说都不是以编程方式成立的:包含查询:
(我知道一些AR-find-includes make t#{n} .c#{m}重命名所有属性,可以想象为这些查询添加条件以限制连接集的结果;但是其他人做n_joins + 1个数字迭代地对id设置的查询,我不确定如何破解AR来编辑这些迭代查询.)
Will Arel允许我们构造ActiveRecord查询,在使用includes()时指定结果关联的模型对象?
例如:
User :has_many posts( has_many :comments)
User.all(:include => :posts) #say I wanted the post objects to have their
#comment counts loaded without adding a comment_count column to `posts`.
#At the post level, one could do so by:
posts_with_counts = Post.all(:select => 'posts.*, count(comments.id) as comment_count',
:joins => 'left outer join comments on comments.post_id = posts.id',
:group_by => 'posts.id') #i believe
#But it seems impossible to do so while …Run Code Online (Sandbox Code Playgroud)