Rails Union hack,如何将两个不同的查询放在一起

发布于 2024-08-07 15:45:05 字数 1023 浏览 7 评论 0原文

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

表格看起来像:

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 联合的任何信息...

I have a query which searches two separate fields in the same table... looking for locations which are most likely a specific city, but could also be a country... ie the need for two fields.

Table looks like:

Country    City

Germany    Aachen
USA        Amarillo
USA        Austin

Result:

Keyword   Sideinfo

Aachen    Germany
USA       Country
Austin    USA
Germany   Country 

Basically I'm wondering if there is a more concise way to do this because I had to use two separate queries then add them together, sort them, etc. (which works fine):

  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

I couldn't find any information on how to unions using ActiveRecord...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

甜心小果奶 2024-08-14 15:45:05

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

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

Doing an UNION query is not natively possible with ActiveRecord. So there are two solutions :

  • Using find_by_sql to build your query as you want it. I wouldn't advise for it.
  • Using a plugin like union to do a UNION sql query.
舂唻埖巳落 2024-08-14 15:45:05

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

I found a neat hack using select .
For example if you want to make a union between User and OtherUser .

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

this will generate this SQL

"SELECT id from other_users union select id FROM users " 

If you have scopes with the conditions you can use the ActiveRecord::Relation where_values method

condition = OtherUser.example_condtion_scope.where_values.join(' ')
User.select("id from other_users where #{contition}")
套路撩心 2024-08-14 15:45:05

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

Using the union plugin, it now works beautifully thanks:

  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
风启觞 2024-08-14 15:45:05

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

This is now possible in 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文