Существует таблица Mysql с различными устройствами, которые необходимо отсортировать по 3м категориям с помощью checkbox.
Сама таблица:
CREATE TABLE IF NOT EXISTS `test_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`phone_name` varchar(255) DEFAULT NULL,
`price` int(11) DEFAULT NULL,
`samsung` tinyint(1) DEFAULT NULL,
`apple` tinyint(1) DEFAULT NULL,
`nokia` tinyint(1) DEFAULT NULL,
`touchscreen` tinyint(1) DEFAULT NULL,
`qwerty` tinyint(1) DEFAULT NULL,
`classic` tinyint(1) DEFAULT NULL,
`single_core` tinyint(1) DEFAULT NULL,
`dual_core` tinyint(1) DEFAULT NULL,
`quad_core` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `test_table` (`id`, `phone_name`, `price`, `samsung`, `apple`,
`nokia`, `touchscreen`, `qwerty`, `classic`, `single_core`, `dual_core`, `quad_core`)
VALUES
(1, 'Samsung Galaxy S4', 470, 1, 0, 0, 1, 0, 0, 0, 0, 1),
(2, 'Samsung Chat', 220, 1, 0, 0, 1, 1, 0, 1, 0, 0),
(3, 'Iphone 4', 380, 0, 1, 0, 1, 0, 0, 0, 1, 0),
(4, 'Iphone 5', 550, 0, 1, 0, 1, 0, 0, 0, 0, 1),
(5, 'Nokia Lumia 520', 150, 0, 0, 1, 1, 0, 0, 0, 1, 0),
(6, 'Nokia E72', 250, 0, 0, 1, 0, 1, 0, 1, 0, 0);
index.html
<div id="filter">
<h2>Filter options</h2>
<div><input type="checkbox" id="samsung" name="samsung"> <label for="samsung">samsung</label></div>
<div><input type="checkbox" id="apple" name="apple"> <label for="apple">apple</label></div>
<div><input type="checkbox" id="nokia" name="nokia"> <label for="nokia">nokia</label></div>
<div><input type="checkbox" id="touchscreen" name="touchscreen"> <label for="touchscreen">touchscreen</label></div>
<div><input type="checkbox" id="qwerty" name="qwerty"> <label for="qwerty">qwerty</label></div>
<div><input type="checkbox" id="classic" name="classic"> <label for="classic">classic</label></div>
<div><input type="checkbox" id="single_core" name="single_core"> <label for="single_core">single_core</label></div>
<div><input type="checkbox" id="dual_core" name="dual_core"> <label for="dual_core">dual_core</label></div>
<div><input type="checkbox" id="quad_core" name="quad_core"> <label for="quad_core">quad_core</label></div>
</div>
<script src="jquery-3.2.1.min.js"></script>
<script src="common.js"></script>
common.js
function getEmployeeFilterOptions(){
var opts = [];
$checkboxes.each(function(){
if(this.checked){
opts.push(this.name);
}
});
return opts;
}
function updateEmployees(opts){
$.ajax({
type: "POST",
url: "submit.php",
dataType : 'json',
cache: false,
data: {filterOpts: opts},
success: function(records){
$('#mobile-phones tbody').html(makeTable(records));
},
error: function(data) {
console.log("ERROR");
}
});
}
var $checkboxes = $("input:checkbox");
$checkboxes.on("change", function(){
var opts = getEmployeeFilterOptions();
updateEmployees(opts);
});
updateEmployees();
submit.php
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test_database', 'root', '');
$select = 'SELECT id, phone_name, price';
$from = ' FROM test_table';
$where = ' WHERE TRUE';
$opts = isset($_POST['filterOpts'])? $_POST['filterOpts'] : array('');
if (in_array("samsung", $opts)){
$where .= " OR samsung = 1";
}
if (in_array("apple", $opts)){
$where .= " OR apple = 1";
}
if (in_array("nokia", $opts)){
$where .= " OR nokia = 1";
}
if (in_array("touchscreen", $opts)){
$where .= " OR touchscreen = 1";
}
if (in_array("qwerty", $opts)){
$where .= " OR qwerty = 1";
}
if (in_array("classic", $opts)){
$where .= " OR classic = 1";
}
if (in_array("single_core", $opts)){
$where .= " OR single_core = 1";
}
if (in_array("dual_core", $opts)){
$where .= " OR dual_core = 1";
}
if (in_array("quad_core", $opts)){
$where .= " OR quad_core = 1";
}
$sql = $select . $from . $where;
$statement = $pdo->prepare($sql);
$statement->execute();
$results = $statement->fetchAll(PDO::FETCH_ASSOC);
$json = json_encode($results);
echo($json);
?>
Проблема в том, что использовать AND нельзя, т.к. при выборе нескольких элементов ajax возвращает пустой массив, а при использовании OR в любом случае возвращается массив со всеми 6-ю телефонами из таблицы. Есть ли рациональный способ фильтрации по 3-м категориям?
Стандартные варианты отбора из списка по набору фильтров таковы:
1) Для любой СУБД
SELECT select_fieldset
FROM tables
WHERE (property, value) IN (список пар свойство-значение)
GROUP BY /* id */ groupby_fieldset
HAVING COUNT(*) = (количество пар свойство-значение)
2) Для MySQL это можно реализовать и в такой форме:
SELECT fieldset
FROM tables
GROUP BY id
HAVING SUM((property, value) IN (список пар свойство-значение)) = (количество пар свойство-значение)
Само собой оба способа предполагают хранение данных, нормализованное в EAV. Для денормализованного хранения (в показанной структуре) придётся извращаться, собирая свойства из отдельных полей в одно значение, которое затем стандартно проверять на соответствие маски (value AND mask = mask). Или писать какое-то многоэтажное безобразие типа
(field1 AND check1) + ... + (fieldN AND checkN) = count(check=1)
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
ЗдравствуйтеВ форме есть поле <input type="file" name="filename" /> При отправке формы идёт проверка
Пытаюсь разобраться с websocket'ами на phpЕсть веб хостинг (сайт), нужно подключиться к нему по сокетам