Объединение «ANDs» и «OR» в сложном запросе WHERE - Часть 2

Я тянул свои волосы с этим запросом последние 2 дня и прочитал и перечитал 2 других похожих сообщения без везения.

Сценарий: Я собираю два входа от пользователя: Test ID Code и адрес электронной почты, который они использовали при отправке теста. Код проверки - это цифры и может содержать букву в начале, но средство тестирования может оставить этот номер, поэтому я добавляю письмо к переменной в запросе (причина для «newtidcode», которую вы увидите ниже). Они могут также предоставить до 4-х адресов электронной почты тестеру при отправке (причина для тестирования на 4 возможности электронной почты).

Вот мой запрос:

    $query->select($db->quoteName(array('tidcode', 'cdcode','email1', 'email2', 'email3', 'email4', 'status')))
        ->from($db->quoteName('#__tid_codes'))
        ->where($db->quoteName('tidcode').' = '.$db->quote($tidcode), 'OR')
        ->where($db->quoteName('tidcode').' = '.$db->quote($newtidcode), 'AND')
        ->where('('.$db->quoteName('email1').' = '.$db->quote($email).' OR '.$db->quoteName('email2').' = '.$db->quote($email).' OR '.$db->quoteName('email3').' = '.$db->quote($email).' OR '.$db->quoteName('email4').' = '.$db->quote($email).')');

Здесь созданный SQL-оператор:

SELECT `tidcode`,`cdcode`,`email1`,`email2`,`email3`,`email4`,`status` FROM `#__tid_codes` WHERE `tidcode` = '10348' OR `tidcode` = 'F10348' OR (`email1` = '[email protected]' OR `email2` = '[email protected].net' OR `email3` = '[email protected]' OR `email4` = '[email protected]')

Как вы можете видеть OR до того, как электронное письмо должно быть И, как указано во втором заявлении «где». Я даже пытался использовать такие массивы состояний, как показано ниже, и все еще сталкивался с тем же.

$conditions1 = array(
    $db->quoteName('tidcode')." = ".$db->quote($tidcode),
    $db->quoteName('tidcode')." = ".$db->quote($newtidcode)
);
$conditions2 = array (
    $db->quoteName('email1')." = ".$db->quote($email),
    $db->quoteName('email2')." = ".$db->quote($email),
    $db->quoteName('email3')." = ".$db->quote($email),
    $db->quoteName('email4')." = ".$db->quote($email)
);

Это мой первый набег в JDatabase, запрашивающий эту сложность. У меня это приложение отлично работает в стандартном HTML и PHP, но пытается перейти на Joomla. Любая помощь высоко ценится.

7 голосов | спросил TJM 18 MaramFri, 18 Mar 2016 03:37:51 +03002016-03-18T03:37:51+03:0003 2016, 03:37:51

2 ответа


6

Второй параметр where, называемый $glue, не работает так, как вы могли ожидать.

Это исходный код функции where:

public function where($conditions, $glue = 'AND')
{
    if (is_null($this->where))
    {
        $glue = strtoupper($glue);
        $this->where = new JDatabaseQueryElement('WHERE', $conditions, " $glue ");
    }
    else
    {
        $this->where->append($conditions);
    }
    return $this;
}

Вы можете видеть, что он принимает только $ glue первого «WHERE», который вы добавляете к вашему запросу.

Я нашел дополнительную информацию об этой проблеме здесь , но информация может быть устаревшим.

Решение

Сохраняйте 2 переменные, $ conditions1 и $ conditions2, а затем создайте свой запрос следующим образом:

$query->select($db->quoteName(array('tidcode', 'cdcode','email1', 'email2', 'email3', 'email4', 'status')))
    ->from($db->quoteName('#__tid_codes'))
    ->where(implode(' OR ', $conditions1))
    ->where('(' . implode(' OR ', $conditions2) . ')');

Что приведет к этому запросу:

SELECT `tidcode`,`cdcode`,`email1`,`email2`,`email3`,`email4`,`status` FROM `#__tid_codes` WHERE `tidcode` = '10348' OR `tidcode` = 'F10348' AND (`email1` = '[email protected]' OR `email2` = '[email protected]' OR `email3` = '[email protected]' OR `email4` = '[email protected]')
ответил fruppel 18 MarpmFri, 18 Mar 2016 14:06:59 +03002016-03-18T14:06:59+03:0002 2016, 14:06:59
0
  

Это немного многословно, но если вы когда-нибудь столкнетесь с сложными выражениями where() или не знаете о приоритете оператора , пожалуйста, прочитайте это как минимум один раз .

Ваш вопрос немного неоднозначен в отношении того, как следует оценивать условия предложения WHERE. Эта страница является подходящим местом, чтобы упомянуть Приоритет оператора . Если не указано иное, мы все можем предположить, что приоритет работает так, как вам нужно.

Однако, прежде чем я начну объяснять влияние этого правила, я сначала хочу сконденсировать логику третьей /заключительной части вашего предложения WHERE (сопоставление по электронной почте).

`email1` = '[email protected]'
OR `email2` = '[email protected]'
OR `email3` = '[email protected]'
OR `email4` = '[email protected]'

... может быть написано гораздо более лаконично ( D.R.Y. ):

'[email protected]' IN (`email1`, `email2`, `email3`, `email4`)

Теперь я продемонстрирую приоритет оператора , используя это сжатое выражение.

  • A будет tidcode сравнение
  • tidcode будет newtidcode сравнение
  • B будет email
  

И s оцениваются до ИЛИ s (см. более раннюю гиперссылку)

newtidcode совпадает с C ... и я думаю, что это то, что вы хотите.

Если вы хотите, чтобы email оценивался до A OR B AND C, вам нужно было бы быть явным с круглыми скобками вроде: A OR (B AND C).


Тем не менее, я предлагаю два разных решения для синтаксиса Joomla.

Один вызов метода WHERE : (много ширины строки, но читается как raw sql)

A OR B

Два метода WHERE вызывает : (уменьшенная ширина строки, но читается меньше как raw sql)

AND C

Оба производят:

(A OR B) AND C


Для сравнения следующие фрагменты сначала оценивают ->where("tidcode = " . $db->q($tidcode) . " OR tidcode = " . $db->q($newtidcode) . " AND " . $db->q($email) . " IN (email1, email2, email3, email4)"); ! :

->where("tidcode = " . $db->q($tidcode), "OR")
->where("tidcode = " . $db->q($newtidcode) . " AND " . $db->q($email) . " IN (email1, email2, email3, email4)");

и

WHERE tidcode = '10348' OR tidcode = 'F10348' AND '[email protected]' IN (email1, email2, email3, email4)

произвести (через OR):

->where("tidcode = " . $db->q($tidcode))
->extendWhere("OR", "tidcode = " . $db->q($newtidcode))
->extendWhere("AND", $db->q($email) . " IN (email1, email2, email3, email4)");

... НО , если вы DO хотите сначала оценить ->where("tidcode = " . $db->q($tidcode)) ->orWhere("tidcode = " . $db->q($newtidcode)) ->andWhere($db->q($email) . " IN (email1, email2, email3, email4)"); , а затем переупаковать первые два условия WHERE с помощью $query->dump().

WHERE 
(
(tidcode = '10348') OR 
(tidcode = 'F10348')) AND 
('[email protected]' IN (email1, email2, email3, email4))

, который производит:

OR
ответил mickmackusa 11 J0000006Europe/Moscow 2018, 09:01:24

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132