代码之家  ›  专栏  ›  技术社区  ›  holden

Rails Union Hack,如何将两个不同的查询拉到一起

  •  13
  • holden  · 技术社区  · 15 年前

    我有一个查询搜索同一表中的两个独立字段…寻找最有可能是一个特定城市,但也可能是一个国家的地点…需要两个领域。

    表格如下:

    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进行联合的信息…

    4 回复  |  直到 9 年前
        1
  •  7
  •   Damien MATHIEU    15 年前

    ActiveRecord在本机上无法执行联合查询。所以有两种解决方案:

    • 使用 find_by_sql 根据需要构建查询。我不建议这样做。
    • 使用类似的插件 union 执行联合SQL查询。
        2
  •  3
  •   lesce    12 年前

    我用select找到了一个很好的黑客。 例如,如果要在用户和其他用户之间进行联合。

    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}")
    
        3
  •  2
  •   holden    15 年前

    使用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
    
        4
  •  1
  •   Mudassir Ali    9 年前

    这在轨道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)