rails union hack,如何将两个不同的查询拉到一起

我有一个查询,它搜索同一个表中的两个单独的字段…寻找最有可能是特定城市的位置,但也可能是一个国家……即需要两个字段。

表看起来像:

Country City Germany Aachen USA Amarillo USA Austin 

结果:

 Keyword Sideinfo Aachen Germany USA Country Austin USA Germany Country 

基本上我想知道是否有更简洁的方法来做这个,因为我必须使用两个单独的查询然后将它们添加在一起,排序等等(这很好):

  def self.ajax(search) countries = Location.find(:all, :select=> 'country AS keyword, "Country" AS sideinfo', :joins => :hotels, :conditions => [ 'hotels.email IS NOT NULL AND country LIKE ?', "#{search}%" ], :group => :country ) cities = Location.find(:all, :select=> 'city AS keyword, country AS sideinfo', :joins => :hotels, :conditions => [ 'hotels.email IS NOT NULL AND city LIKE ?', "#{search}%" ], :group => :city ) out = cities + countries out = out.sort { |a,b| a.keyword  b.keyword } out.first(8) end 

我找不到任何关于如何使用ActiveRecord的联盟的信息……

ActiveRecord本身不可能执行UNION查询。 所以有两种解决方案:

  • 使用find_by_sql根据需要构建查询。 我不会建议。
  • 使用像union这样的插件来执行UNION sql查询。

我找到了一个使用select的整洁黑客。 例如,如果要在User和OtherUser之间建立联合。

 User.select('id from other_users union select id') 

这将生成此SQL

 "SELECT id from other_users union select id FROM users " 

如果您有具有条件的作用域,则可以使用ActiveRecord :: Relation where_values方法

 condition = OtherUser.example_condtion_scope.where_values.join(' ') User.select("id from other_users where #{contition}") 

使用union插件,它现在可以很好地运行了,谢谢:

  def self.ajax3(search) Location.union( [{ :select => 'city AS keyword, country AS sideinfo', :joins => :hotels, :conditions => [ 'email IS NOT NULL AND city LIKE ?', "#{search}%" ]}, { :select => 'country AS keyword, "Country" AS sideinfo', :joins => :hotels, :conditions => [ 'email IS NOT NULL AND country LIKE ?', "#{search}%" ]}] ) end 

现在可以在Rails 4中实现,

 locations = Location.arel_table hotels = Hotel.arel_table countries = Location .select(locations[:country].as("keyword")) .joins(:hotels) .where(hotels[:email].not_eq(nil)) .where(locations[:country].matches("#{search}%")) cities = Location .select(locations[:city].as("keyword")) .joins(:hotels) .where(hotels[:email].not_eq(nil)) .where(locations[:city].matches("#{search}%")) union = countries.union(cities) result = Location.from(locations.create_table_alias(union, :locations).to_sql)