it-swarm.asia

كيف أستخدم "NOT IN" في استعلام؟

ما هي الطريقة الصحيحة لكتابة استعلام يحتوي على "NOT IN" باستخدام عبارة الشرط؟

استفساري هو ما يلي:

SELECT DISTINCT nid FROM node WHERE language NOT IN 
  (SELECT language 
    FROM languages WHERE language = 'ab');

لقد جربت شيئًا مما يلي:

$query->condition('n.' . $key, $value, 'not in (select language from 
  languages where language = $value)');
26
JurgenR

في المثال المحدد ، يجب عليك ببساطة كتابة الشرط على النحو التالي:

$query->condition('n.language', 'ab', '<>');

في الحالة العامة ، حيث تحتاج إلى تحديد الصفوف في قاعدة بيانات استنادًا إلى القيم التي تم إرجاعها من استعلام فرعي ، يجب مراعاة ما يلي:

  • يتم قبول "NOT IN" كعامل تشغيل من SelectQuery::condition(). في الواقع ، سيتم تنفيذ الاستعلام التالي:

    $query = db_select('node', 'n')->fields('n');
    $query->condition('n.nid', array(1, 2, 3), 'NOT IN');
    $nodes = $query->execute();
    
    foreach ($nodes as $node) {
      dsm($node->nid);
    }
    
  • كما ورد في الشروط الشرطية ("Subselects") ، SelectQuery::condition() يقبل أيضًا كائنًا ينفذ SelectQueryInterface كقيمة لـ $value ، مثل ذلك الذي تم إرجاعه بواسطة db_select() ؛ تكمن المشكلة في أنه يمكنك فقط استخدامه عندما تكون قيمة $operator تساوي "IN". راجع لا تعمل الاختيارات الفرعية في شروط DBTNG ، إلا عند استخدامها كقيمة لـ IN .

الطريقة الوحيدة التي يمكنني من خلالها رؤية استخدام عامل التشغيل "NOT IN" مع استعلام فرعي في condition هي:

  • تنفيذ الاستعلام الفرعي للحصول على صفيف
  • تنفيذ الاستعلام الرئيسي تعيين الشرط كما في المقتطف التالي

    $query->condition($key, $subquery_result, 'NOT IN');
    

    $subquery_result هو المصفوفة التي تحتوي على نتيجة الاستعلام الفرعي.

خلافًا لذلك ، يمكنك استخدام where() كما قال الآخرون ، والتي تقبل سلسلة للجزء من الاستعلام الذي تريد إضافته.

ضع في اعتبارك أن db_select() أبطأ من db_query() ؛ يجب عليك استخدام الأول عندما تعرف أنه يمكن تعديل الاستعلام بواسطة وحدات أخرى. خلاف ذلك ، إذا لم يكن من المفترض أن تستخدم الوحدات الأخرى hook_query_alter() لتغيير الاستعلام الخاص بك ، يجب عليك استخدام db_query().
في حالة الوصول إلى العقد ، إذا كنت بحاجة إلى الحصول على العقد التي يمكن للمستخدم الوصول إليها فقط ، فأنت بحاجة إلى استخدام db_select() وإضافة 'node_access' كعلامة لل الاستعلام مع SelectQuery::addTag() . على سبيل المثال ، blog_page_last() يستخدم الكود التالي.

  $query = db_select('node', 'n')->extend('PagerDefault');
  $nids = $query
  ->fields('n', array('nid', 'sticky', 'created'))
    ->condition('type', 'blog')
    ->condition('status', 1)
    ->orderBy('sticky', 'DESC')
    ->orderBy('created', 'DESC')
    ->limit(variable_get('default_nodes_main', 10))
    ->addTag('node_access')
    ->execute()
    ->fetchCol();

يتم استخدام رمز مماثل book_block_view() .

$select = db_select('node', 'n')
  ->fields('n', array('title'))
  ->condition('n.nid', $node->book['bid'])
  ->addTag('node_access');
$title = $select->execute()->fetchField();
38
kiamlaluno

عند كتابة الاستعلامات المعقدة يجب عليك بالتأكيد استخدام db_query() بدلاً من db_select() .

  1. لا يمكنك كتابة بند NOT IN مع استعلام فرعي باستخدام Drupal (إنها تعرف المشكلة قيد العمل).
  2. إذا لم تكن بحاجة إلى أن يكون الاستعلام ديناميكيًا (وبالتالي تتم إعادة كتابته بواسطة وحدات أخرى) ، لا تهتم محاولة كتابة مثل هذا السؤال المعقد باستخدام db_select().
  3. الاستعلامات الفرعية غير مدعومة جيدًا حتى الآن (انظر الإجابة السابقة الخاصة بي) وإذا كنت معتادًا على كتابة SQL ، فمن السهل استخدام db_query().

فيما يتعلق باستعلامك ، لست متأكدًا من سبب رغبتك في استخدام استعلام فرعي (ما لم تبسط مثالك)؟ يمكنك كتابتها بسهولة مثل هذا:

SELECT nid 
FROM node n INNER JOIN languages l ON n.language = l.language
WHERE language NOT IN ('ab')

DISTINCT ليس ضروريًا لأن nid هو مفتاح أساسي لذا لن يتم تكراره.

3
tostinni

هناك أيضًا حيث () والتي تسمح بإضافة شرط تعسفي إلى الاستعلام.

مثال:

$query->where('n.language NOT IN (SELECT language FROMlanguages WHERE language = :lang)', array(':lang' => $value));

كما ذكر keithm ، يجب عليك استخدام db_select () و addTag ('node_access') عند تحديد العقد التي يتم عرضها بعد ذلك للمستخدمين.

2
Berdir

أسهل طريقة لاستخدام db_select مع تحديد IN IN الفرعي هي استخدام القليل غير المعروف

$ الاستعلام-> أين

لإضافة تعسفي حيث الشرط.

على سبيل المثال:

  // 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));  
  $count = $query->countQuery()->execute()->fetchField();
  drupal_set_message($count);
1
David Thomas

حيث يكون $ subquery_values ​​عبارة عن صفيف من $ key => $ nid format نتيجة لاستعلام فرعي

$query->condition('node.nid', array_values($subquery_values), "NOT IN");

أنه يعمل بشكل جيد.

0
Riccardo Ravaro