запрос по двум и более значениям в одной колонке

wild83

Новичок
запрос по двум и более значениям в одной колонке

таблица "ss_product_options_values"


productID | optionID | option_value |

первый | 7 | 7,0 |
второй | 7 | 7,0 |
третий | 7 | 7,2 |

первый | 11 | 15 |
второй | 11 | 16 |
третий | 11 | 17 |


Например нужно выбрать те "productID" у которых ("optionID" = 7 и "option_value" = 7,0) И ("optionID" = 11 и "option_value" = 15)

Результат на выходе - "первый"

формирую запрос:

SELECT DISTINCT(`productID`) FROM `ss_product_options_values` WHERE (`optionID` = 7 AND `option_value` = '7,0') AND (`optionID` = 11 AND `option_value` = '15')

в итоге ничего не выводит
 

wild83

Новичок
пробую по другому....

SELECT DISTINCT(`productID`) FROM `ss_product_options_values` WHERE (`optionID` = 7 AND `option_value` = '7,0') OR (`optionID` = 11 AND `option_value` = '15')

Выводит "первый", "второй"

Хотя "второй" `optionID` = 11 И `option_value` = '16'
что не верно
 

phprus

Moderator
Команда форума
wild83
Можно воспользоваться связкой GROUP BY, HAVING и COUNT().
 

dimagolov

Новичок
wild83, объясни, у тебя в `option_value` = '7,0' 7 и 0 это два отдельных числа или части одной строки?
 

dimagolov

Новичок
тебе нужно джойнить таблицу на себя:
[sql]select t1.productID from tab as t1
inner join tab as t2 on t1.productID = t2.productID
where (t1.`optionID` = 7 AND t1.`option_value` = '7,0') AND (t2.`optionID` = 11 AND t2.`option_value` = '15')[/sql]
 

wild83

Новичок
Спасбо камрад! Я тоже начал думать как создать 2 таблицы, по одному за просу на каждую и потом их объеденить по колонке productID. Но как это написать?
А у тебя уже готовый запрос.
Спасибо ещё раз, буду разбираться.
 

phprus

Moderator
Команда форума
dimagolov
А потом надо будет joinить таблицы 3 раза, потом 4 и так далее?

Более универсальное решение:
[sql]
SELECT t1.productID
FROM tab AS t1
WHERE (
t1.`optionID` = 7 AND t1.`option_value` = '7,0'
) OR (
t1.`optionID` = 11 AND t1.`option_value` = '15'
)
GROUP BY t1.productID
HAVING COUNT(t1.productID) = 2
[/sql]
Правда я не знаю как будет выполняться этот запрос, но тут все-равно придется смотреть и сравнивать планы различных запросов, что-бы понять что лучше использовать.

по одному за просу на каждую и потом их объеденить по колонке productID. Но как это написать?
Помимо оператора объединения UNION есть еще оператор пересечения результирующих наборов INTERSECT.
 

wild83

Новичок
phprus
>А потом надо будет joinить таблицы 3 раза, потом 4 и так далее?

Я все параметры загоняю в массив а потом в цикле формирую и таблицы и параметры. Тоже думал что с таблицами геморно будет, оказалось очень удобно.

Эксперементировать с другими вариантами пока не хочется.

-~{}~ 11.03.10 12:16:

Вот кусок кода если интересно:

$diameter = $_GET['diameter'];
$koldir = $_GET['koldir'];
$diamdir = $_GET['diamdir'];

$width = $_GET['width'];
$dia = $_GET['dia'];
$et = $_GET['et'];


$tables = ""; //здесь будем собирать внутренние таблицы отборов (сколько параметров отбора задано столько будет и таблиц)
$query_values = ""; //здесь будем собирать опции отборов


$elements_array = array();

if ($width != 'Не важно')
$elements_array[] = array(7, $width); //Ширина обода: OPTION_DISKS_WIDTH 7

if ($diameter != 'Не важно')
$elements_array[] = array(11, $diameter); //Диаметр диска: OPTION_DISKS_DIAMETER 11

if ($koldir != 'Не важно')
$elements_array[] = array(19, $koldir); //Кол-во крепежных отверстий: OPTION_DISKS_KOLDIR 19

if ($diamdir != 'Не важно')
$elements_array[] = array(12, $diamdir); //Диаметр расположения крепежных отверстий: OPTION_DISKS_DIAMDIR 12

if ($dia != 'Не важно')
$elements_array[] = array(14, $dia); //Диаметр центрального отверстия (ЦО): OPTION_DISKS_DIA 14

if ($et != 'Не важно')
$elements_array[] = array(13, $et); //Вылет (ЕТ): OPTION_DISKS_ET 13


// Собираем в цикле запрос
foreach ($elements_array as $key => $value) {

if ($key == 0)// если первый элемент
{

//Если это опция OPTION_DISKS_DIAMDIR (12) то нужно использовать "LIKE" вместо "=" из-за того что в базе эти размеры в виде "4x100"
//а вид отбора в виде "100". Поэтому идёт условие.

if ($value[0] != 12) $query_values .= "WHERE (main.`optionID` =$value[0] AND main.`option_value` = '$value[1]') ";
else $query_values .= "WHERE (main.`optionID` =$value[0] AND main.`option_value` LIKE '%$value[1]%') ";

}
else{
$tab_name = "t$key";
$tables .= "INNER JOIN ss_product_options_values AS $tab_name ON main.productID = $tab_name.productID ";

//Если то же самое. Используем в запросе "LIKE" вместо "=" если это опция OPTION_DISKS_DIAMDIR (12).
if ($value[0] != 12) $query_values .= "AND ($tab_name.`optionID` =$value[0] AND $tab_name.`option_value` = '$value[1]') ";
else $query_values .= "AND ($tab_name.`optionID` =$value[0] AND $tab_name.`option_value` LIKE '%$value[1]%') ";
}

}


// Если были выбраны параметры
if (count($elements_array)>0) $q = "SELECT main.productID FROM ss_product_options_values AS main ";
//Если ни один параметр не был выбран. То отбираем все диски.
//Отбираем для этого товары по параметру "Кол-во крепежных отверстий" > 0, который заполнен только у дисков.
else $q = "SELECT DISTINCT(`productID`) FROM `ss_product_options_values` WHERE (`optionID` = ".OPTION_DISKS_KOLDIR." AND `option_value` > 0)";

//Отправляем запрос
$lib_mysql->query($q.$tables.$query_values);
 
Сверху