【问题标题】:rails union hack, how to pull two different queries togetherrails union hack,如何将两个不同的查询放在一起
【发布时间】:2009-10-18 10:54:41
【问题描述】:

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

表格如下:

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

【问题讨论】:

标签: sql ruby-on-rails ruby activerecord union


【解决方案1】:

使用 ActiveRecord 本身无法执行 UNION 查询。所以有两种解决方案:

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

【讨论】:

  • Union 现在 3 岁了。任何人都有更新的解决方案
  • @BillLeeper 虽然您的评论是在 12 年发布的,但如果您仍在寻找它,请查看我的答案
  • @BillLeeper github.com/brianhempel/active_record_union 是一个更好的宝石。在 ActiveRecord 作用域上使用联合而不丑。
【解决方案2】:

我发现了一个使用 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}")

【讨论】:

    【解决方案3】:

    使用 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】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-12
        • 2011-07-22
        • 1970-01-01
        • 2016-11-29
        • 1970-01-01
        • 2021-09-08
        相关资源
        最近更新 更多