Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails查询,其中有许多关系匹配查询不';不存在_Ruby On Rails_Activerecord - Fatal编程技术网

Ruby on rails Rails查询,其中有许多关系匹配查询不';不存在

Ruby on rails Rails查询,其中有许多关系匹配查询不';不存在,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,我有一个订阅模型,它有许多交易s 我想查找与某个查询匹配的事务不存在的所有订阅 这是产生正确结果的手动循环代码。但是,我想使用where查询来做同样的事情 # Find all subs that don't have a transaction where foo == bar subs = [] Subscription.all.each do |sub| if sub.transactions.find { |tran| tran.foo == 'bar' } == nil s

我有一个
订阅
模型,它有许多
交易
s

我想查找与某个查询匹配的事务不存在的所有订阅

这是产生正确结果的手动循环代码。但是,我想使用
where
查询来做同样的事情

# Find all subs that don't have a transaction where foo == bar
subs = []
Subscription.all.each do |sub|
  if sub.transactions.find { |tran| tran.foo == 'bar' } == nil
    subs.push(sub)
  end
end
我尝试了很多不同的选择,但没有一个能产生正确的结果:

Subscription.includes(:transactions).where("NOT EXISTS (SELECT null FROM subscriptions.transactions where transactions.foo = 'bar')")

Subscription.includes(:transactions).where("(select count(*) from transactions where foo='bar') = 0")

Subscription.where(Transaction.where("transactions.foo != 'bar'").limit(1).count == 0)

Subscription.joins(:transactions).group('subscriptions.id').having('count(transactions.foo = 'bar') = 0')

Subscription.where(Transaction.group().where("count(transactions.foo != 'bar') = 0"))

Subscription.where('(SELECT COUNT(*) FROM transactions WHERE transactions.foo = 'bar') =  0')

Transaction.left_outer_joins(:transactions).group("transactions.id").having("count(transactions.id)>0")

Subscription.left_outer_joins(:transactions).where.not(transactions: {foo: 'bar'})

您可以首先选择foo等于bar的所有事务。 然后,您可以选择以上结果中未包含的所有订阅ID,这将提供如下活动记录查询:

Subscription.where.not(id: Transaction.where('foo = ?', 'bar').select(:subscription_id).uniq)
SELECT * FROM subscriptions WHERE (subscriptions.id NOT IN (SELECT DISTINCT transactions.subscription_id WHERE transactions.foo = 'bar'))
这将生成如下所示的SQL查询:

Subscription.where.not(id: Transaction.where('foo = ?', 'bar').select(:subscription_id).uniq)
SELECT * FROM subscriptions WHERE (subscriptions.id NOT IN (SELECT DISTINCT transactions.subscription_id WHERE transactions.foo = 'bar'))

嗯,这不管用。它给了我比完全存在的更多的订阅对象。我认为原因是它向我们提供了订阅,其中transactions.foo!=bar,即使其中一个transactions.foo==bar。例如,如果订阅有两个trans,其中一个是foo!=其中foo==bar,看起来这个仍然返回那个sub,即使我们不想要它。如果订阅甚至包含一个foo==bar的事务,我们就不想返回它。我觉得合并
count
可能是一种方式。这是我想要的伪代码:
sub.where(count(sub.transactions.where(foo==bar))==0)
。我已经更新了我的答案,请你试一试(不幸的是我没有在电脑前试一试)就是这样做的!稍微修改一下:
Subscription.where.not(id:Transaction.where('foo=?','bar')。选择(:Subscription_id).uniq.map{e|e.Subscription_id})
(添加了返回id数组而不是事务对象的映射。也许有一种方法可以直接用SQL来实现这一点),您可以使用active record提供的采集方法。然后它应该变成Subscription.where.not(id:transaction.where('foo=?','bar').pull(:id.uniq))