Wie schreibe ich eine Abfrage, die 'NOT IN' enthält, mit einer Bedingungsanweisung?
Meine Frage ist die folgende:
SELECT DISTINCT nid FROM node WHERE language NOT IN
(SELECT language
FROM languages WHERE language = 'ab');
Ich habe Folgendes versucht:
$query->condition('n.' . $key, $value, 'not in (select language from
languages where language = $value)');
SELECT nid FROM node WHERE language != 'ab'
?Antworten:
Im konkreten Beispiel schreiben Sie die Bedingung einfach wie folgt:
Im allgemeinen Fall, in dem Sie die Zeilen in einer Datenbank basierend auf den von einer Unterabfrage zurückgegebenen Werten auswählen müssen, sollten Sie Folgendes berücksichtigen:
"NOT IN" wird als Operator von akzeptiert
SelectQuery::condition()
. Tatsächlich würde die folgende Abfrage ausgeführt:Akzeptiert , wie in den Bedingungsklauseln ("Unterauswahlen") angegeben,
SelectQuery::condition()
auch ein Objekt, dasSelectQueryInterface
als Wert für implementiert ist$value
, z. B. das von zurückgegebene Objektdb_select()
. Das Problem ist, dass Sie es tatsächlich nur verwenden können, wenn der Wert von$operator
gleich ist"IN"
. Siehe Unterauswahlen funktionieren nicht unter DBTNG-Bedingungen, außer wenn sie als Wert für IN verwendet werden .Die einzige Möglichkeit, den Operator "NOT IN" mit einer Unterabfrage in zu verwenden,
condition
besteht darin,Führen Sie die Hauptabfrage aus, indem Sie die Bedingung wie im folgenden Snippet festlegen
$subquery_result
ist das Array, das das Ergebnis der Unterabfrage enthält.Andernfalls könnten Sie,
where()
wie bereits erwähnt, eine Zeichenfolge für den Teil der Abfrage verwenden, den Sie hinzufügen müssen.Denken Sie daran, dass
db_select()
das langsamer istdb_query()
; Sie sollten die erste verwenden, wenn Sie wissen, dass die Abfrage von anderen Modulen geändert werden kann. Andernfalls sollten Sie verwenden, wenn andere Module nichthook_query_alter()
zum Ändern Ihrer Abfrage verwendet werden sollendb_query()
.Wenn Sie beim Zugriff auf Knoten nur die Knoten abrufen müssen, auf die ein Benutzer Zugriff hat, müssen Sie mit als Tag der Abfrage verwenden
db_select()
und hinzufügen . Zum Beispiel verwendet den folgenden Code.'node_access'
SelectQuery::addTag()
blog_page_last()
Ein ähnlicher Code wird von verwendet
book_block_view()
.quelle
Wenn Sie komplexe Abfragen schreiben, sollten Sie auf jeden Fall
db_query()
statt verwendendb_select()
.NOT IN
mit der aktuellen Drupal-Datenbank-API keine Klausel mit einer Unterabfrage schreiben (es ist ein bekanntes Problem, das derzeit bearbeitet wird).db_select()
.db_query()
.Bezüglich Ihrer Anfrage bin ich mir nicht sicher, warum Sie eine Unterabfrage verwenden möchten (es sei denn, Sie haben Ihr Beispiel vereinfacht). Sie können es leicht so schreiben:
DISTINCT
ist nicht notwendig, danid
es sich um einen Primärschlüssel handelt, damit er nicht dupliziert wird.quelle
Es gibt auch where () , mit dem der Abfrage eine beliebige where-Bedingung hinzugefügt werden kann.
Beispiel:
Wie bereits erwähnt, müssen Sie db_select () und addTag ('node_access') verwenden, um Knoten auszuwählen, die den Benutzern angezeigt werden.
quelle
Eine einfachere Möglichkeit, db_select mit einer NOT IN-Unterauswahl zu verwenden, besteht darin, nur die wenig bekannten zu verwenden
$ query-> where
eine beliebige where-Bedingung hinzufügen.
z.B:
quelle
Dabei ist $ subquery_values ein Array des Formats $ key => $ nid als Ergebnis einer Unterabfrage
es funktioniert gut.
quelle