ActiveRecord Query Union - PullRequest
       34

ActiveRecord Query Union

81 голосов
/ 14 июля 2011

Я написал пару сложных запросов (по крайней мере для меня) с интерфейсом запросов Ruby on Rail:

watched_news_posts = Post.joins(:news => :watched).where(:watched => {:user_id => id})
watched_topic_posts = Post.joins(:post_topic_relationships => {:topic => :watched}).where(:watched => {:user_id => id})

Оба эти запроса отлично работают сами по себе. Оба возвращают объекты Post. Я хотел бы объединить эти сообщения в одну ActiveRelation. Поскольку в какой-то момент может быть сотни тысяч сообщений, это необходимо сделать на уровне базы данных. Если бы это был запрос MySQL, я мог бы просто использовать оператор UNION. Кто-нибудь знает, могу ли я сделать нечто подобное с интерфейсом запросов RoR?

Ответы [ 12 ]

0 голосов
/ 29 мая 2019

Вот как я присоединился к SQL-запросам с помощью UNION в своем собственном приложении ruby ​​on rails.

Вы можете использовать нижеприведенное в качестве вдохновения для своего собственного кода.

class Preference < ApplicationRecord
  scope :for, ->(object) { where(preferenceable: object) }
end

Ниже представлен UNIONгде я присоединился к областям видимости.

  def zone_preferences
    zone = Zone.find params[:zone_id]
    zone_sql = Preference.for(zone).to_sql
    region_sql = Preference.for(zone.region).to_sql
    operator_sql = Preference.for(Operator.current).to_sql

    Preference.from("(#{zone_sql} UNION #{region_sql} UNION #{operator_sql}) AS preferences")
  end
0 голосов
/ 21 февраля 2018

Эллиот Нельсон ответил хорошо, за исключением случая, когда некоторые отношения пусты. Я бы сделал что-то подобное:

def union_2_relations(relation1,relation2)
sql = ""
if relation1.any? && relation2.any?
  sql = "(#{relation1.to_sql}) UNION (#{relation2.to_sql}) as #{relation1.klass.table_name}"
elsif relation1.any?
  sql = relation1.to_sql
elsif relation2.any?
  sql = relation2.to_sql
end
relation1.klass.from(sql)

конец

...