Просто чтобы обновить это, так как кажется, что многие приходят к этому, если вы используете 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>)
ruby-on-rails
rails-activerecord
Тоби Столяр
источник
источник
Person.all(:name.not => ['bob','rick','steve'])
Ответы:
Рельсы 4+:
Рельсы 3:
Где
actions
находится массив с:[1,2,3,4,5]
источник
Topic.where('id NOT IN (?)', (actions.empty? ? '', actions)
. Он все равно будет равен нулю, но я обнаружил, что передаваемый массив обычно генерируется фильтром, который будет возвращать[]
по крайней мере и никогда не будет равен нулю. Я рекомендую проверить Squeel, DSL поверх Active Record. Тогда вы можете сделать:,Topic.where{id.not_in actions}
ноль / пусто / или иначе..empty?
для.blank?
и вы ноль доказательствоК вашему сведению, в Rails 4 вы можете использовать
not
синтаксис:источник
Вы можете попробовать что-то вроде:
Возможно, вам нужно сделать
@forums.map(&:id).join(',')
. Я не могу вспомнить, будет ли Rails вносить аргумент в список CSV, если он перечислим.Вы также можете сделать это:
источник
Используя Arel:
или, если предпочтительнее:
и так как рельсы 4 на:
Пожалуйста, обратите внимание, что в конечном итоге вы не хотите, чтобы forum_ids был списком идентификаторов, а скорее подзапросом, если это так, то вам нужно сделать что-то подобное, прежде чем получать темы:
таким образом вы получаете все в одном запросе: что-то вроде:
Также обратите внимание, что в конечном итоге вы не хотите делать это, а хотите объединиться - что может быть более эффективным.
источник
EXPLAIN
!Чтобы расширить ответ @Trung Lê, в Rails 4 вы можете сделать следующее:
И вы могли бы сделать еще один шаг вперед. Если вам нужно сначала отфильтровать только опубликованные темы, а затем отфильтровать ненужные идентификаторы, вы можете сделать это:
Rails 4 делает это намного проще!
источник
Принятое решение не выполняется, если
@forums
оно пустое Чтобы обойти это, я должен был сделатьИли, если вы используете Rails 3+:
источник
Вам должно хватить большинства приведенных выше ответов, но если вы делаете гораздо больше таких предикатов и сложных комбинаций, проверьте Squeel . Вы сможете сделать что-то вроде:
источник
Возможно, вы захотите взглянуть на плагин meta_where Эрни Миллера. Ваш оператор SQL:
... можно выразить так:
Райан Бейтс из Railscasts создал хороший скринкаст, объясняющий MetaWhere .
Не уверен, что это то, что вы ищете, но, на мой взгляд, это выглядит лучше, чем встроенный SQL-запрос.
источник
В оригинальном посте конкретно упоминается использование числовых идентификаторов, но я пришел сюда в поисках синтаксиса для выполнения NOT IN с массивом строк.
ActiveRecord прекрасно с этим справится и для вас:
источник
Могут ли эти идентификаторы форума быть выработаны прагматично? например, можете ли вы найти эти форумы как-нибудь - если это так, вы должны сделать что-то вроде
Что было бы более эффективно, чем делать SQL
not in
источник
Этот способ оптимизирует читабельность, но он не так эффективен с точки зрения запросов к базе данных:
источник
Вы можете использовать sql в ваших условиях:
источник
Спекуляция от Джонни:
используя срыв, а не отображение элементов
найдено через railsconf 2012 10 вещей, о которых вы не знали
источник
Когда вы запрашиваете пустой массив, добавьте «<< 0» к массиву в блоке where, чтобы он не возвращал «NULL» и не прерывал запрос.
Если действия могут быть пустым или пустым массивом.
источник
Topic.where("id NOT IN (?)", actions.presence || [0])
Вот более сложный запрос «не в», использующий подзапрос в рельсах 4 с использованием squeel. Конечно, очень медленно по сравнению с эквивалентным SQL, но эй, это работает.
Первые 2 метода в области являются другими областями, которые объявляют псевдонимы cavtl1 и tl1. << не является оператором в squeel.
Надеюсь, это кому-нибудь поможет.
источник