it-swarm.com.de

"WHERE NOT IN (SELECT ...)" mit SelectQuery?

Ist es möglich, einem SelectQuery Objekt eine WHERE NOT IN (SELECT...) - Klausel hinzuzufügen? Ich habe mir SelectQuery :: condition () angesehen und es scheint diese Syntax nicht zuzulassen:

public SelectQuery::condition($field, $value = NULL, $operator = NULL)

Es scheint nur Wertvergleichsausdrücke zuzulassen. Gibt es eine andere Methode, die diese Syntax bereitstellt?

Ich betrachte Bedingungen in der Größenordnung von Tausenden von Werten, daher scheint es ineffizient zu sein, eine Reihe von AND value <> x Bedingungen.

6
user1359

Was Sie suchen, ist SelectQuery :: existes () , leider scheint es nicht mit "allgemeiner Methode" zu funktionieren, um eine solche Klausel zu erstellen:
Normalerweise setzen Sie in einer EXISTS -Klausel einen JOIN auf Tabellen außerhalb Ihrer Unterabfrage wie folgt:

SELECT n.nid
FROM node n
WHERE EXISTS (
  SELECT NULL
  FROM users u
  WHERE u.uid = n.uid
  AND u.status = 0)

Dies gibt die Knoten blockierter Benutzer zurück (ja, es kann leicht ohne EXISTS erstellt werden, aber es dient Lehrzwecken;).

Das Problem hierbei ist, dass die Bedingung exists keine "externe Verknüpfung" unterstützt, die u.uid = n.uid Teil, so dass Sie eine völlig unabhängige Abfrage erstellen müssen, die meiner Meinung nach nicht sehr effizient ist.
In Drupal schreiben Sie Folgendes:

$query = db_select('node', 'n')
  ->fields('n', array('nid'));
$subquery = db_select('node', 'n2')
  ->fields('n2', array('nid'))
  ->join('users', 'u', 'n2.uid = u.uid'
  ->condition('u.status', 0);
$query->condition('', $subquery, 'EXISTS');
$result = $query->execute();

Sie können auch db_query () verwenden, wie Sie es früher in Drupal 6 und natürlich SelectQuery :: notExists () getan haben.

8
tostinni

Eine einfachere Möglichkeit, db_select mit einer NOT IN-Unterauswahl zu verwenden, ist die Verwendung

$ query-> where

eine beliebige where-Bedingung hinzufügen.

z.B:

  // Count query for users without rid 3
  $query = db_select('users', 'u');
  $query->fields('u', array('uid'));
  $query->where('u.uid NOT IN(select uid from {users_roles} where rid = :rid)', array(':rid' => 3));  
  $result = $query->countQuery()->execute()->fetchField();
  drupal_set_message($result);
2
David Thomas

Tatsächlich können Sie SelectQuery :: condition () verwenden, um Unterauswahlen wie folgt zu erstellen:

$query = db_select('users', 'u')
  ->fields('u', array('uid'))
  ->condition('u.uid', db_select('users_roles', 'r')->fields('r', array('uid')), 'NOT IN');

Wenn wir diese Abfrage mit der Funktion dpq () von devel drucken, wird Folgendes ausgegeben:

SELECT u.uid AS uid
FROM 
{users} u
WHERE  (u.uid NOT IN  (SELECT r.uid AS uid
FROM 
{users_roles} r))

Ich hoffe das hilft ;-)

2
Jelle

Ich glaube, das würde dir helfen.

$query->where('n.nid NOT IN (:nids)', array(
    ':nids' => implode(',', $nids)
));
0
Vlad Stratulat