ох уж это where
Хочу составить условие для нахождения товаров, по передаваемым значениям опций.
Вот часть кода
Данный код в виде SQL выглядит так
Хотя товар есть, который должен попасть под эту выборку.
Заменяю AND на OR
Не хочу дальше вас запутывать своими рассказами, лучше к вопросу
— как корректно ставить where для разных вариантов? Чтобы скажем отобрать только товары у кого высота строго 152 и при этом и давление строго 900? Потому как я наглядно вижу, что два раза переданный where объединяется через AND, хотя вот тут написано docs.modx.com/current/en/extending-modx/xpdo/class-reference/xpdoquery/xpdoquery.where
— как сделать чтобы два передаваемых массива where объединялись через OR вместо AND?
спасибо.
Вот часть кода
$q = $modx->newQuery('msProductOption');
$q->innerJoin('msProduct', 'msProduct', 'msProduct.id=msProductOption.product_id');
$q->where(array('msProductOption.key' => 'height', 'msProductOption.value:IN'=> [152]));
$q->where(array(
'msProductOption.key' => 'presure',
'msProductOption.value:IN'=> [900],
));
Идея в том, чтобы отобрать товары у которых И высота равна 152 и одновременно и давление 900.Данный код в виде SQL выглядит так
SELECT DISTINCT(msProductOption.value), msProduct.id FROM `modx_ms2_product_options` AS `msProductOption` JOIN `modx_site_content` `msProduct` ON msProduct.id=msProductOption.product_id WHERE ( ( `msProductOption`.`key` = 'height' AND `msProductOption`.`value` IN ('152') ) AND ( `msProductOption`.`key` = 'presure' AND `msProductOption`.`value` IN ('900') ) ) ORDER BY msProductOption.value ASC
и ничего не возвращает, как в modx так и напрямую выполненный в mysql.Хотя товар есть, который должен попасть под эту выборку.
Заменяю AND на OR
WHERE ( ( `msProductOption`.`key` = 'height' AND `msProductOption`.`value` IN ('152') ) OR ( `msProductOption`.`key` = 'presure' AND `msProductOption`.`value` IN ('900') ) )
получаю вполне логичный результат — все товару и кого высота 152 и все товары у кого давление 900Не хочу дальше вас запутывать своими рассказами, лучше к вопросу
— как корректно ставить where для разных вариантов? Чтобы скажем отобрать только товары у кого высота строго 152 и при этом и давление строго 900? Потому как я наглядно вижу, что два раза переданный where объединяется через AND, хотя вот тут написано docs.modx.com/current/en/extending-modx/xpdo/class-reference/xpdoquery/xpdoquery.where
// two arrays used to contain the OR statement within the listed conditionsто есть два массива where по умолчанию соединяются через OR, а на практике не так?
— как сделать чтобы два передаваемых массива where объединялись через OR вместо AND?
спасибо.
Комментарии: 4
Так ты же выбираешь опции
или
или
как сделать чтобы два передаваемых массива where объединялись через OR вместо AND?Вот по той же ссылке которую ты указал есть ответ на твой вопрос:
$query = $xpdo->newQuery('Box');
$query->where(array('width' => 15));
$query->where(array('width' => 10),xPDOQuery::SQL_OR); // you can use orCondition here as well
$boxes = $xpdo->getCollection('Box',$query);
или
$query = $xpdo->newQuery('Box');
$query->where(array(
array( // two arrays used to contain the OR statement within the listed conditions
'width' => 15
),
array(
'width' => 10
)
),xPDOQuery::SQL_OR); // use one array if no additional where statements are used.
$boxes = $xpdo->getCollection('Box',$query);
или
$query = $xpdo->newQuery('Box');
$query->where(array(
array(
'width' => 15
),
array(
'OR:width:=' => 10
)
));
$boxes = $xpdo->getCollection('Box',$query);
Так ты же выбираешь опцииэто был не полный код, полный выглядит так
$q = $modx->newQuery('msProductOption');
$q->innerJoin('msProduct', 'msProduct', 'msProduct.id=msProductOption.product_id');
$q->where(array('msProductOption.key' => 'height', 'msProductOption.value:IN'=> [152]));
$q->where(array(
'msProductOption.key' => 'presure',
'msProductOption.value:IN'=> [900],
));
$q->sortby('msProductOption.value','ASC');
$q->select('DISTINCT(msProductOption.value), msProduct.id');
//$q->where(array('msProductOption.key' => $key));
if (!empty($category)) {
$ids = $modx->getChildIds($category);
$ids[] = $category;
$q->innerJoin('msCategory', 'msCategory', 'msCategory.id=msProduct.parent');
$q->where(array('msCategory.id:IN' => $ids));
}
$q->prepare();
print_r($q->toSQL());
Я пробовал второй и третий код, который вы написали — они не сработали и выдавали ошибки синтаксиса sql. Возможно это связано с тем, что в примерах условие простое КЛЮЧ — Значение. А у меня условие (Опция называется вот так и ее значение вот такое — это первый where и второй — опция называется как-то иначе и ее значение вот такое).Тоесть как-то так
$q->where(array(
'OR:msProductOption.key' => 'presure',
'msProductOption.value:IN'=> [900],
));
приводит к ошибке.А вот первый код, где можно передать дополнительно константу — я пропустил, спасибо.
Но по сути, на данный момент я считаю что sql запрос получается то правильным, по крайней мере составляй я его сам, составил бы так же и два условия ДОЛЖНЫ соединятся через AND, если я хочу найти товар у которого одна опция равна чему то и вторая тоже равна чему то. Но почему-то этого не происходит, как только два условия
WHERE ( ( `msProductOption`.`key` = 'height' AND `msProductOption`.`value` IN ('152') ) AND ( `msProductOption`.`key` = 'presure' AND `msProductOption`.`value` IN ('900') ) )
идут через AND то результат выборки пуст, хотя точно есть товар у котороо высота 154 и давление 900.В общем, где-то торможу я)
идут через AND то результат выборки пуст, хотя точно есть товар у котороо высота 154 и давление 900.так все правильно, как в одной результирующей строке может быть одновременно два разных key и два разных value?
если ты посмотришь EXPLAIN своего запроса, то наверняка увидишь Impossible where
тебе нужно приджойнить таблицу опций еще раз, тогда ты сможешь выбирать из одной один ключ и значение, а из другой — другие
$c = $modx->newQuery(msProduct::class, [
'Height.key' => 'height',
'Height.value' => '152',
'Pressure.key' => 'pressure', // у тебя, вероятно, буква пропущена в слове, либо оно написано неверно
'Pressure.value' => '900',
]);
$c->select(['msProduct.id', 'msProduct.pagetitle']);
$c->leftJoin('msProductOption', 'Height', 'Height.product_id = msProduct.id');
$c->leftJoin('msProductOption', 'Pressure', 'Pressure.product_id = msProduct.id');
if ($c->prepare() && $c->stmt->execute()) {
return $c->stmt->fetchAll(PDO::FETCH_KEY_PAIR);
}
Да это разумно, спасибо
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.