0

搜索鉴于这些机型:轨道4,活动记录严格的阵列,协会

class Farm < ActiveRecord::Base 
    has_and_belongs_to_many :animals 
end 

Class Animal < ActiveRecord::Base 
    has_and_belongs_to_many :farms 
end 

我需要寻找farmsduckspigscows但没有catsdogs

这种查询不起作用:

Animal.joins(:farms) 
.where('animals.name IN ? AND animals.name NOT IN ?', 
good_animal_names, bad_animal_names) 

由于它搜索农场与任何动物。我需要搜索具有所有期望的农场而没有其他农场的农场。

我也试图与SQL像这样的东西:

SELECT farms.id, farms.name 
FROM farms 
INNER JOIN animals_farms ON animals_farms.farm_id = farms.id 
INNER JOIN animals ON animals_farms.animal_id = animals.id 
    WHERE animals.name IN (['ducks', 'pigs', 'cows']) 
    AND animals.name NOT IN (['dogs', 'cats']) 
GROUP BY farms.id, farms.name 
    HAVING COUNT(unique(animals.name)) = 3 

但我不知道,如果animals.name NOT IN真的会排除农场有没有动物或只养殖场没有他们中的一个。真正的数据库很难验证结果。

此外,能够在Active Record或Arel中执行查询应该很棒,但SQL中的任何建议都非常值得欢迎。

数据库是Oracle,我对Oracle没有太多的经验,但是大多数用PostgreSQL的查询都在这里工作。

回答

0

嗯,我想我有一个可能的SQL解决方案。请评论,如果你能看到任何问题或知道更好的方法来做到这一点。

WITH included_animals as (SELECT farms.id, farms.name 
    FROM farms 
    INNER JOIN animals_farms ON animals_farms.farm_id = farms.id 
    INNER JOIN animals ON animals_farms.animal_id = animals.id 
    WHERE animals.name IN ('ducks', 'pigs', 'cows') 
    GROUP BY farms.id, farms.name 
    HAVING COUNT(unique(animals.name)) = 3), 
not_included_animals as (SELECT farms.id, farms.name 
    FROM farms 
    INNER JOIN animals_farms ON animals_farms.farm_id = farms.id 
    INNER JOIN animals ON animals_farms.animal_id = animals.id 
    WHERE animals.name IN ('dogs', 'cats') 
    GROUP BY farms.id, farms.name) 
SELECT id, name 
FROM included_animals 
MINUS --use EXCEPT if riding PostgreSQL 
SELECT id, name 
FROM not_included_animals 
0

假设你只有两类动物 - (好/坏),而你只需要好动物。你可以试试这个吗?

Farm.joins(:animals).where.not(animals: {name: bad_animal_names})

希望它能帮助!

+0

谢谢,但哪里是好动物? – 2014-12-19 01:13:04

+0

它会列出除坏动物以外的所有其他动物是什么意思。请尝试在您的应用程序中运行 – uday 2014-12-19 01:16:39

+0

第二种方法:'Farm.joins(:animals).where(animals:{name:good_animal_names})' – uday 2014-12-19 02:43:43