Est-il possible d'ajouter une clause WHERE NOT IN (SELECT...)
à un objet SelectQuery
? Je regardais SelectQuery :: condition () , et il ne semble pas autoriser cette syntaxe:
public SelectQuery::condition($field, $value = NULL, $operator = NULL)
Il semble seulement permettre des expressions de comparaison de valeurs. Existe-t-il une autre méthode qui fournit cette syntaxe?
Je regarde des conditions de l'ordre de milliers de valeurs, il semble donc inefficace d'avoir un tas de AND value <> x
conditions.
Ce que vous recherchez est SelectQuery :: exist () , malheureusement, il ne semble pas fonctionner avec une "méthode courante" pour construire une telle clause:
Normalement, dans une clause EXISTS
, vous placez un JOIN sur des tables en dehors de votre sous-requête comme ceci:
SELECT n.nid
FROM node n
WHERE EXISTS (
SELECT NULL
FROM users u
WHERE u.uid = n.uid
AND u.status = 0)
Cela renvoie les nœuds des utilisateurs bloqués (oui, il peut être construit facilement sans EXISTS
mais c'est à des fins pédagogiques;).
Le problème ici est que la condition exists
ne prend pas en charge la "liaison externe", la u.uid = n.uid
partie donc vous devez construire une requête complètement indépendante qui n'est pas très efficace à mon humble avis.
Dans Drupal vous écrirez ceci:
$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();
Vous pouvez également utiliser db_query () comme vous le faisiez dans Drupal 6 et bien sûr SelectQuery :: notExists () est disponible.
Un moyen plus simple d'utiliser db_select avec une sous-sélection NOT IN consiste simplement à utiliser
pour ajouter une condition arbitraire where.
par exemple:
// 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);
En fait, vous pouvez utiliser SelectQuery :: condition () pour créer des sous-sélections comme ceci:
$query = db_select('users', 'u')
->fields('u', array('uid'))
->condition('u.uid', db_select('users_roles', 'r')->fields('r', array('uid')), 'NOT IN');
Si nous imprimons cette requête en utilisant la fonction dpq () de devel, elle affichera:
SELECT u.uid AS uid
FROM
{users} u
WHERE (u.uid NOT IN (SELECT r.uid AS uid
FROM
{users_roles} r))
J'espère que ça aide ;-)
Je crois que cela vous aiderait.
$query->where('n.nid NOT IN (:nids)', array(
':nids' => implode(',', $nids)
));