2013-04-02 44 views
1

我遇到的情况,我有SQL的地方加入查询链,然后在另外一些时候,我需要追加哪些需要同样的加入条件,但我不知道这一点是否该连接已经存在于范围内。例如:避免重复在Rails的ActiveRecord的查询连接

@foo = Foo.joins("INNER JOIN foos_bars ON foos_bars.foo_id = foos.id") 
.... 
@foo.joins(:bars).where(bars: { id: 1 }) 

这将产生有关重复表/别名的SQL错误。

我写的SQL之所以在一审手动加入是改善经典的轨道AREL连接将产品两个内连接凡在我来说,我只需要一个效率。

有没有解决这个推荐的方法是什么?例如,查看当前在范围内的联接的一些方法。

回应评论:

随着has_and_belongs_to_many关系的Rails产生两个INNER JOINS这样的:

SELECT "journals".* FROM "journals" 
INNER JOIN "categories_journals" 
    ON "categories_journals"."journal_id" = "journals"."id" 
INNER JOIN "categories" 
    ON "categories"."id" = "categories_journals"."category_id" 
WHERE "categories"."id" = 1 

而我相信我能做到这一点,而不是:

SELECT "journals".* FROM "journals" 
INNER JOIN "categories_journals" 
    ON "categories_journals"."journal_id" = "journals"."id" 
WHERE "categories_journals"."category_id" = 1 

纠正我,如果我错了。

+0

你做了什么样的分析,证明做加入的你更“有效”的方式实际上是更好?其实,是什么让你觉得你只需要一个连接?即使您反复尝试反复加入同一张表,AREL也不会建立不必要的连接。 – messick

+0

我更新了我的问题,因为评论@messick太长了。 –

+0

我建议让AREL做它的事情。您的解决方案正在击败ORM的一个主要优点,它是'自动'具有映射到数据库表的对象的。如果加入到Categories表格真的是一个性能问题,我会回头想想Rails是否真的是你想要使用的东西。 – messick

回答

1

的解决方案是普遍使用的字符串连接。不知道我的Rails实际上是uniq的字符串连接 - 所以只要他们是字符串相同这个问题不会发生。

This article把我的气味,笔者表现出完全一样的问题,因为我和补丁Rails的,它看起来像补丁是很久以前实现。我不认为这是完美的。应该有一种方法来处理散列参数联接和字符串联接,并且在重叠时不会弹出。可能会看到,如果我可以修补的..

编辑:

我做了几个基准测试,看看是否我真的很担心没什么与否(加盟的两种方法之间):

1.9.3p194 :008 > time = Benchmark.realtime { 1000.times { a = Incident.joins("INNER JOIN categories_incidents ON categories_incidents.incident_id = incidents.id").where("categories_incidents.category_id = 1") } } 
=> 0.042458 
1.9.3p194 :009 > time = Benchmark.realtime { 1000.times { a = Incident.joins(:categories).where(categories: { id: 1 }) } } 
=> 0.152703 

我不是一个普通的基准测试人员,所以我的基准测试可能并不完美,但在我看来,好像我的更高效的方法确实能够在大型查询或大量查询上实现真实世界的性能改进。

加入我做的方式的缺点是,如果Category不存在但仍记录在连接表中,那么可能会导致一些问题,否则可以通过更彻底的连接来避免。