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>)
나는 이것을 사용하고있다 :
Topic.where('id NOT IN (?)', Array.wrap(actions))
다음 actions
과 같은 배열은 어디에 있습니까?[1,2,3,4,5]
편집하다:
Rails 4 표기법 :
Article.where.not(title: ['Rails 3', 'Rails 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
Most of the answers above should suffice you but if you are doing a lot more of such predicate and complex combinations check out Squeel. You will be able to doing something like:
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)}
You may want to have a look at the meta_where plugin by Ernie Miller. Your SQL statement:
SELECT * FROM topics WHERE forum_id NOT IN (<@forum ids>)
...could be expressed like this:
Topic.where(:forum_id.nin => @forum_ids)
Ryan Bates of Railscasts created a nice screencast explaining MetaWhere.
Not sure if this is what you're looking for but to my eyes it certainly looks better than an embedded SQL query.
The original post specifically mentions using numeric IDs, but I came here looking for the syntax for doing a NOT IN with an array of strings.
ActiveRecord will handle that nicely for you too:
Thing.where(['state NOT IN (?)', %w{state1 state2}])
Can these forum ids be worked out in a pragmatic way? e.g. can you find these forums somehow - if that is the case you should do something like
Topic.all(:joins => "left join forums on (forums.id = topics.forum_id and some_condition)", :conditions => "forums.id is null")
Which would be more efficient than doing an SQL not in
This way optimizes for readability, but it's not as efficient in terms of database queries:
# Retrieve all topics, then use array subtraction to
# find the ones not in our list
Topic.all - @forums.map(&:id)
You can use sql in your conditions:
Topic.find(:all, :conditions => [ "forum_id NOT IN (?)", @forums.map(&:id)])
Piggybacking off of jonnii:
Topic.find(:all, :conditions => ['forum_id not in (?)', @forums.pluck(:id)])
using pluck rather than mapping over the elements
found via railsconf 2012 10 things you did not know rails could do
When you query a blank array add "<< 0" to the array in the where block so it doesn't return "NULL" and break the query.
Topic.where('id not in (?)',actions << 0)
If actions could be an empty or blank array.
Here is a more complex "not in" query, using a subquery in rails 4 using squeel. Of course very slow compared to the equivalent sql, but hey, it works.
scope :translations_not_in_english, ->(calmapp_version_id, language_iso_code){
join_to_cavs_tls_arr(calmapp_version_id).
joins_to_tl_arr.
where{ tl1.iso_code == 'en' }.
where{ cavtl1.calmapp_version_id == my{calmapp_version_id}}.
where{ dot_key_code << (Translation.
join_to_cavs_tls_arr(calmapp_version_id).
joins_to_tl_arr.
where{ tl1.iso_code == my{language_iso_code} }.
select{ "dot_key_code" }.all)}
}
The first 2 methods in the scope are other scopes which declare the aliases cavtl1 and tl1. << is the not in operator in squeel.
Hope this helps someone.
참고URL : https://stackoverflow.com/questions/4307411/how-to-express-a-not-in-query-with-activerecord-rails
'Programming' 카테고리의 다른 글
iPhone 방향이 세로에서 가로로 변경 될 때 HTML 글꼴 크기 유지 (0) | 2020.05.10 |
---|---|
C에서 소수점 이하 2 자리로 반올림 (0) | 2020.05.10 |
Java 컴파일러 레벨이 설치된 Java 프로젝트 패싯 버전과 일치하지 않습니다. (0) | 2020.05.10 |
다른 테이블의 값이있는 mysql 업데이트 열 (0) | 2020.05.10 |
Express에서 여러 파일에 라우트 핸들러를 포함시키는 방법은 무엇입니까? (0) | 2020.05.10 |