Juste pour mettre à jour cela car il semble que beaucoup de gens y viennent, si vous utilisez Rails 4, regardez les réponses de Trung Lê` et VinniVidiVicci.
Topic.where.not(forum_id:@forums.map(&:id))
Topic.where(published:true).where.not(forum_id:@forums.map(&:id))
J'espère qu'il existe une solution simple qui n'implique pas find_by_sql
, sinon je suppose que cela devra fonctionner.
J'ai trouvé cet article qui fait référence à ceci:
Topic.find(:all, :conditions => { :forum_id => @forums.map(&:id) })
ce qui est le même que
SELECT * FROM topics WHERE forum_id IN (<@forum ids>)
Je me demande s'il y a un moyen de faire NOT IN
ça, comme:
SELECT * FROM topics WHERE forum_id NOT IN (<@forum ids>)
ruby-on-rails
rails-activerecord
Toby Joiner
la source
la source
Person.all(:name.not => ['bob','rick','steve'])
Réponses:
Rails 4+:
Rails 3:
Où
actions
est un tableau avec:[1,2,3,4,5]
la source
Topic.where('id NOT IN (?)', (actions.empty? ? '', actions)
. Cela casserait toujours sur zéro, mais je trouve que le tableau que vous transmettez est généralement généré par un filtre qui retournera[]
au moins et jamais nul. Je recommande de vérifier Squeel, une DSL au-dessus d'Active Record. Ensuite, vous pouvez faireTopic.where{id.not_in actions}
:, nil / vide / ou autre..empty?
pour.blank?
et vous êtes nulle épreuvePour info, dans Rails 4, vous pouvez utiliser la
not
syntaxe:la source
Vous pouvez essayer quelque chose comme:
Vous pourriez avoir besoin de le faire
@forums.map(&:id).join(',')
. Je ne me souviens pas si Rails va l'argument dans une liste CSV si elle est énumérable.Vous pouvez également faire ceci:
la source
Utilisation d'Arel:
ou, si vous préférez:
et depuis les rails 4 sur:
Veuillez noter que finalement vous ne voulez pas que le forum_ids soit la liste des identifiants, mais plutôt une sous-requête, si c'est le cas, vous devriez faire quelque chose comme ça avant d'obtenir les sujets:
de cette façon, vous obtenez tout en une seule requête: quelque chose comme:
Notez également que finalement vous ne voulez pas faire cela, mais plutôt une jointure - ce qui pourrait être plus efficace.
la source
EXPLAIN
!Pour développer la réponse @Trung Lê, dans Rails 4, vous pouvez effectuer les opérations suivantes:
Et vous pourriez aller plus loin. Si vous devez d'abord filtrer uniquement les sujets publiés, puis filtrer les identifiants dont vous ne voulez pas, vous pouvez le faire:
Rails 4 le rend tellement plus facile!
la source
La solution acceptée échoue si elle
@forums
est vide. Pour contourner cela, je devais faireOu, si vous utilisez Rails 3+:
la source
La plupart des réponses ci-dessus devraient vous suffire, mais si vous faites beaucoup plus de ces combinaisons de prédicats et complexes, consultez Squeel . Vous pourrez faire quelque chose comme:
la source
Vous voudrez peut-être jeter un œil au plugin meta_where d'Ernie Miller. Votre instruction SQL:
... pourrait s'exprimer ainsi:
Ryan Bates de Railscasts a créé un joli screencast expliquant MetaWhere .
Je ne sais pas si c'est ce que vous recherchez, mais à mes yeux, cela semble certainement mieux qu'une requête SQL intégrée.
la source
Le message d'origine mentionne spécifiquement l'utilisation d'ID numériques, mais je suis venu ici à la recherche de la syntaxe pour faire un NOT IN avec un tableau de chaînes.
ActiveRecord s'en chargera également pour vous:
la source
Ces identifiants de forum peuvent-ils être élaborés de manière pragmatique? par exemple, pouvez-vous trouver ces forums en quelque sorte - si tel est le cas, vous devriez faire quelque chose comme
Ce qui serait plus efficace que de faire un SQL
not in
la source
De cette façon, la lisibilité est optimisée, mais ce n'est pas aussi efficace en termes de requêtes de base de données:
la source
Vous pouvez utiliser sql dans vos conditions:
la source
Ferroutage hors de jonnii:
utiliser la plumaison plutôt que la cartographie sur les éléments
trouvé via railsconf 2012 10 choses que vous ne saviez pas que les rails pouvaient faire
la source
Lorsque vous interrogez un tableau vide, ajoutez "<< 0" au tableau dans le bloc where pour qu'il ne renvoie pas "NULL" et interrompez la requête.
Si les actions peuvent être un tableau vide ou vide.
la source
Topic.where("id NOT IN (?)", actions.presence || [0])
Voici une requête "pas dans" plus complexe, utilisant une sous-requête dans les rails 4 à l'aide de Squeel. Bien sûr, très lent par rapport au sql équivalent, mais bon, ça marche.
Les 2 premières méthodes de l'étendue sont d'autres étendues qui déclarent les alias cavtl1 et tl1. << est l'opérateur not in de squeel.
J'espère que cela aide quelqu'un.
la source