[ruby-on-rails] ActiveRecord / Rails로 NOT IN 쿼리를 표현하는 방법?
Rails 4를 사용하고 있다면 Trung Lê`와 VinniVidiVicci의 답변을 살펴보십시오.
Topic.where.not(forum_id:@forums.map(&:id))
Topic.where(published:true).where.not(forum_id:@forums.map(&:id))
나는 포함되지 않는 쉬운 해결책이 있기를 바라고 있습니다 find_by_sql
. 그렇지 않으면 그것이 작동해야한다고 생각합니다.
Topic.find(:all, :conditions => { :forum_id => @forums.map(&:id) })
이것은 같은
SELECT * FROM topics WHERE forum_id IN (<@forum ids>)
그와 관련이있는 방법이 있는지 궁금합니다 NOT IN
.
SELECT * FROM topics WHERE forum_id NOT IN (<@forum ids>)
답변
레일 4+ :
Article.where.not(title: ['Rails 3', 'Rails 5'])
레일 3 :
Topic.where('id NOT IN (?)', Array.wrap(actions))
다음 actions
과 같은 배열은 어디에 있습니까?[1,2,3,4,5]
답변
참고로 Rails 4에서는 다음 not
구문 을 사용할 수 있습니다 .
Article.where.not(title: ['Rails 3', 'Rails 5'])
답변
다음과 같은 것을 시도해 볼 수 있습니다.
Topic.find(:all, :conditions => ['forum_id not in (?)', @forums.map(&:id)])
해야 할 수도 있습니다 @forums.map(&:id).join(',')
. Rails가 열거 가능한 경우 CSV 목록에 인수를 표시할지 여부를 기억할 수 없습니다.
당신은 또한 이것을 할 수 있습니다 :
# in topic.rb
named_scope :not_in_forums, lambda { |forums| { :conditions => ['forum_id not in (?)', forums.select(&:id).join(',')] }
# in your controller
Topic.not_in_forums(@forums)
답변
Arel 사용 :
topics=Topic.arel_table
Topic.where(topics[:forum_id].not_in(@forum_ids))
또는 원하는 경우 :
topics=Topic.arel_table
Topic.where(topics[:forum_id].in(@forum_ids).not)
4 번 레일부터
topics=Topic.arel_table
Topic.where.not(topics[:forum_id].in(@forum_ids))
결국 forum_ids가 ID 목록이 아니라 하위 쿼리가되기를 원하지 않으면 주제를 얻기 전에 이와 같은 작업을 수행해야합니다.
@forum_ids = Forum.where(/*whatever conditions are desirable*/).select(:id)
이런 식으로 단일 쿼리로 모든 것을 얻을 수 있습니다.
select * from topic
where forum_id in (select id
from forum
where /*whatever conditions are desirable*/)
또한 결국이 작업을 원하지 않고 오히려 조인이 더 효율적일 수 있습니다.
답변
@Trung Lê 답변을 확장하려면 Rails 4에서 다음을 수행하십시오.
Topic.where.not(forum_id:@forums.map(&:id))
한 걸음 더 나아갈 수 있습니다. 먼저 게시 된 주제 만 필터링 한 다음 원하지 않는 ID 를 필터링 해야하는 경우 다음 을 수행 할 수 있습니다.
Topic.where(published:true).where.not(forum_id:@forums.map(&:id))
Rails 4는 훨씬 쉬워졌습니다!
답변
@forums
비어 있으면 승인 된 솔루션이 실패합니다 . 이 문제를 해결하려면
Topic.find(:all, :conditions => ['forum_id not in (?)', (@forums.empty? ? '' : @forums.map(&:id))])
또는 Rails 3 이상을 사용하는 경우 :
Topic.where( 'forum_id not in (?)', (@forums.empty? ? '' : @forums.map(&:id)) ).all
답변
위의 답변의 대부분은 당신에게 충분하지만, 당신이 많은 술어와 복잡한 조합을 많이하고 있다면 Squeel을 확인하십시오 . 다음과 같은 작업을 수행 할 수 있습니다.
Topic.where{{forum_id.not_in => @forums.map(&:id)}}
Topic.where{forum_id.not_in @forums.map(&:id)}
Topic.where{forum_id << @forums.map(&:id)}