Nur um dies zu aktualisieren, da es scheint, dass viele Leute dazu kommen, wenn Sie Rails 4 verwenden, schauen Sie sich die Antworten von Trung Lê` und VinniVidiVicci an.
Topic.where.not(forum_id:@forums.map(&:id))
Topic.where(published:true).where.not(forum_id:@forums.map(&:id))
Ich hoffe, es gibt eine einfache Lösung, die nicht beinhaltet find_by_sql
, wenn nicht, dann muss das wohl funktionieren.
Ich habe diesen Artikel gefunden, der darauf verweist:
Topic.find(:all, :conditions => { :forum_id => @forums.map(&:id) })
das ist das gleiche wie
SELECT * FROM topics WHERE forum_id IN (<@forum ids>)
Ich frage mich, ob es einen Weg gibt, damit umzugehen NOT IN
, wie:
SELECT * FROM topics WHERE forum_id NOT IN (<@forum ids>)
ruby-on-rails
rails-activerecord
Toby Tischler
quelle
quelle
Person.all(:name.not => ['bob','rick','steve'])
Antworten:
Schienen 4+:
Schienen 3:
Wo
actions
ist ein Array mit:[1,2,3,4,5]
quelle
Topic.where('id NOT IN (?)', (actions.empty? ? '', actions)
. Es würde immer noch auf Null brechen, aber ich finde, dass das Array, das Sie übergeben, normalerweise von einem Filter generiert wird,[]
der mindestens und niemals Null zurückgibt. Ich empfehle Squeel, ein DSL über Active Record. Dann könnten Sie tun :Topic.where{id.not_in actions}
, null / leer / oder anders..empty?
für.blank?
und Sie sind null-Zu Ihrer Information: In Rails 4 können Sie die folgende
not
Syntax verwenden:quelle
Sie können etwas versuchen wie:
Möglicherweise müssen Sie tun
@forums.map(&:id).join(',')
. Ich kann mich nicht erinnern, ob Rails das Argument in eine CSV-Liste aufnehmen wird, wenn es aufzählbar ist.Sie können dies auch tun:
quelle
Verwenden von Arel:
oder, falls bevorzugt:
und da Schienen 4 auf:
Bitte beachten Sie, dass Sie eventuell nicht möchten, dass die forum_ids die IDs-Liste sind, sondern eine Unterabfrage. Wenn ja, sollten Sie Folgendes tun, bevor Sie die Themen abrufen:
Auf diese Weise erhalten Sie alles in einer einzigen Abfrage: so etwas wie:
Beachten Sie auch, dass Sie dies eventuell nicht mehr tun möchten, sondern einen Join - was möglicherweise effizienter ist.
quelle
EXPLAIN
!Um die Antwort von @Trung Lê zu erweitern, können Sie in Rails 4 Folgendes tun:
Und Sie könnten noch einen Schritt weiter gehen. Wenn Sie zuerst nur nach veröffentlichten Themen filtern und dann die nicht gewünschten IDs herausfiltern müssen, können Sie Folgendes tun:
Rails 4 macht es so viel einfacher!
quelle
Die akzeptierte Lösung schlägt fehl, wenn sie
@forums
leer ist. Um dies zu umgehen, musste ich tunOder wenn Sie Rails 3+ verwenden:
quelle
Die meisten der obigen Antworten sollten ausreichen, aber wenn Sie viel mehr solcher Prädikate und komplexen Kombinationen machen, schauen Sie sich Squeel an . Sie können Folgendes tun:
quelle
Vielleicht möchten Sie sich das meta_where-Plugin von Ernie Miller ansehen . Ihre SQL-Anweisung:
... könnte so ausgedrückt werden:
Ryan Bates von Railscasts hat einen schönen Screencast erstellt, der MetaWhere erklärt .
Ich bin mir nicht sicher, ob dies das ist, wonach Sie suchen, aber in meinen Augen sieht es sicherlich besser aus als eine eingebettete SQL-Abfrage.
quelle
Der ursprüngliche Beitrag erwähnt ausdrücklich die Verwendung numerischer IDs, aber ich bin hierher gekommen, um nach der Syntax für ein NOT IN mit einem Array von Zeichenfolgen zu suchen.
ActiveRecord erledigt das auch für Sie:
quelle
Können diese Forum-IDs pragmatisch ausgearbeitet werden? zB kannst du diese Foren irgendwie finden - wenn das der Fall ist, solltest du so etwas tun
Was effizienter wäre als ein SQL
not in
quelle
Diese Methode optimiert die Lesbarkeit, ist jedoch in Bezug auf Datenbankabfragen nicht so effizient:
quelle
Sie können SQL in Ihren Bedingungen verwenden:
quelle
Huckepack von jonnii:
Verwenden Sie das Zupfen, anstatt die Elemente abzubilden
gefunden via railsconf 2012 10 Dinge, von denen Sie nicht wussten, dass Rails sie können
quelle
Wenn Sie ein leeres Array abfragen, fügen Sie dem Array im where-Block "<< 0" hinzu, damit es nicht "NULL" zurückgibt und die Abfrage unterbricht.
Wenn Aktionen ein leeres oder leeres Array sein könnten.
quelle
Topic.where("id NOT IN (?)", actions.presence || [0])
Hier ist eine komplexere "Nicht-In" -Abfrage, bei der eine Unterabfrage in Schienen 4 mit Squeel verwendet wird. Natürlich sehr langsam im Vergleich zum entsprechenden SQL, aber hey, es funktioniert.
Die ersten beiden Methoden im Bereich sind andere Bereiche, die die Aliase cavtl1 und tl1 deklarieren. << ist der nicht in Operator in Squeel.
Hoffe das hilft jemandem.
quelle