Группировка предложений WHERE с помощью Zend_Db_Table_Abstract
Кто-нибудь знает способ группировки where clauses с Zend_Db? В основном у меня есть этот запрос
$sql = $table->select()
->where('company_id = ?', $company_id)
->where('client_email = ?', $client_email)
->orWhere('client_email_alt = ?', $client_email);
Что мне дает это:
SELECT `clients`.* FROM `clients` WHERE (company_id = '1') AND (client_email = '[email protected]') OR (client_email_alt = '[email protected]')
Но мне нужно это, чтобы дать мне это, где сгруппирован оператор OR:
SELECT `clients`.* FROM `clients` WHERE (company_id = '1') AND ((client_email = '[email protected]') OR (client_email_alt = '[email protected]'))
Ответы
Ответ 1
Чтобы достичь этого, вы должны построить предложение grouped в рамках одного вызова метода where
.
Если оба значения условий одинаковы, вы можете сделать это:
$select->where('client_email = ? OR client_email_alt = ?', $client_email)
Если в строке есть несколько заполнителей, метод DB adapter quoteInto
заменит все заполнители на предоставленное значение.
Если вам нужно сгруппировать OR
с разными значениями для каждого поля, вам нужно вручную указать значения. Это немного сложнее:
$select->where(
$db->quoteInto('client_email = ?', $email1) . ' OR ' . $db->quoteInto('client_email_alt = ?', $email2)
); // $db is your instance of Zend_Db_Adapter_*
// You can get it from a Zend_Db_Table_Abstract
//subclass by calling its getAdapter() method
Ответ 2
Вы можете использовать getPart()
, чтобы получить инструкцию WHERE, а затем подключить подзапросы.
$select->where('client_email = ?', $client_email)
->orWhere('client_email_alt = ?', $client_email);
$subquery = $select->getPart(Zend_Db_Select::WHERE);
$select ->reset(Zend_Db_Select::WHERE);
$select ->where('company_id = ?', $company_id)
->where(implode(' ',$subquery));
Ответ 3
Для Zend Framework версии 2 все немного отличается:
См. http://framework.zend.com/apidoc/2.2/classes/Zend.Db.Sql.Predicate.Predicate.html#nest
$table->select()
->where(['company_id'=> $company_id])
->nest
->where('client_email = ?', $client_email)
->or
->where('client_email_alt = ?', $client_email)
->unnest();
работает отлично и чувствует себя намного чище, чем методы ZF1.
Ответ 4
Вначале вы можете сгенерировать подзапрос, затем получить часть "WHERE" и вставить в основной запрос
$subquery = $db->select();
$subquery->orWhere('a>10');
$subquery->orWhere('b<20');
etc..
$subquery = $subquery->getPart(Zend_Db_Select::WHERE);
$select->where(implode(' ',$subquery));
Ответ 5
Мне нужно было комбинировать операторы AND/OR, но с предложениями OR, условно, добавляя их только в некоторых случаях. Это решение является адаптацией того, что я сделал, основываясь на небольших модификациях принятого ответа.
$sql = $table->select()
->where('company_id = ?', $company_id);
$orWhereClauses = [];
// We could add a conditional statement to add this statement
$orWhereClauses[] = $db->quoteInto('client_email = ?', $email1);
// Same applies to this statement
$orWhereClauses[] = $db->quoteInto('client_email_alt = ?', $email2);
$sql->where(implode(" OR ", $orWhereClauses));