我有两张桌子:
sales
period_id
customer_id
product_id
value
total_sales
period_id
customer_id
product_id
value
我想选择period_id
上存在的customer_id
和sales
的所有组合,但不会total_sales
上存在。{1}}。我相信这是一个简短的方法。但我认为每种方法都涉及N + 1个查询。
我该怎么做?
答案 0 :(得分:0)
在我看来,正是这种情况下,与纯粹的ActiveRecord方法不同并将一些SQL引入表中是合理的。这应该很好地完成这个技巧:
Sale.find_by_sql("
SELECT * FROM sales WHERE NOT EXISTS (
SELECT 1 FROM total_sales
WHERE total_sales.period_id = sales.period_id AND
total_sales.customer_id = sales.customer_id)
")
我想它也可以用更多的ActiveRecordish风格完成,但它肯定会失去代码的清晰度。
当然,如果你把它放到你的代码库中,你真的应该将它包装在一个方法中并留在模型中,这样SQL代码至少不会流入控制器。
希望这有帮助!
P.S。哦,这是我用来测试它的SQL小提琴:http://sqlfiddle.com/#!15/eaf1d/1
答案 1 :(得分:0)
如何首先获得匹配的列表,然后使用它来获取您真正想要的行:
unwanted_ids = Sale.joins('inner join total_sales on sales.period_id = total_sales.period_id and sales.customer_id = total_sales.customer_id').pluck('distinct sales.id')
wanted_rows = unwanted_ids.any? Sale.where('id not in (?)', unwanted_ids) : Sale.all
wanted_rows.select(:period_id, :customer_id) #if you only want these two
这样您只需要两个查询。
编辑:
你也可以这样做:
Sale.joins('left outer join total_sales on sales.period_id = total_sales.period_id and sales.customer_id = total_sales.customer_id').where('total_sales.period_id is null')
是否在一个查询中