У меня есть следующая таблица категорий:
+--------+---------------+----------------------------------------+
| ID | Parent ID | Name |
+--------+---------------+----------------------------------------+
| 1 | 0 | Computers |
| 2 | 1 | Apple |
| 3 | 1 | HP |
| 4 | 2 | Macbook Air |
| 5 | 2 | Macbook Pro |
| 6 | 1 | Dell |
| 7 | 6 | Inspiron |
| 8 | 6 | Alienware |
| 9 | 8 | Alienware 13 |
| 10 | 8 | Alienware 15 |
| 11 | 8 | Alienware 17 |
| 12 | 0 | Smartphones |
| 13 | 12 | Apple |
| 14 | 12 | Samsung |
| 15 | 12 | LG |
+--------+---------------+----------------------------------------+
Скажем, у меня есть следующая таблица продуктов:
+--------+---------------+----------------------------------------+
| ID | Category ID | Name |
+--------+---------------+----------------------------------------+
| 1 | 13 | Apple iPhone 8 |
| 2 | 13 | Apple iPhone 8 Plus |
| 3 | 14 | Samsung Galaxy S8 |
+--------+---------------+----------------------------------------+
Следуя запросу, я выбираю все продукты в категории:
SELECT
id,
name
FROM
products
WHERE
category_id = ?
Хорошо, мой вопрос:
Продукт Apple iPhone 8 находится в категории Apple, это подкатегория категории Смартфоны. Если я заменил '?' в моем запросе с 13 (идентификатор категории Apple), я получаю продукт. Когда я заменяю '?' в моем запросе с 12 (идентификатор категории смартфонов), я не получаю продукт. Я хочу выбрать все продукты в категории или в одной из категорий child/grandchild/.... Как я могу сделать это с помощью одного запроса (если это возможно)?
1) ВОПРОС. Я беру запрос из этого ответа. Как создать иерархический рекурсивный запрос MySQL. Прочтите его для полного объяснения запроса. Запрос предполагает, что родительский идентификатор будет меньше, чем идентификаторы дочерних элементов (например, 19 меньше 20,21,22).
select * from products where 'Category ID' in
(select ID from
(select * from categories order by 'Parent ID', ID) categories_sorted,
(select @pv := '12') initialisation
where (find_in_set('Parent ID', @pv) > 0
and @pv := concat(@pv, ',', ID)) or ID = @pv)
Вы должны установить "12" в качестве родительской категории.
2) Через два раздела в PHP, которые будут проходить до тех пор, пока у вас не будет всех идентификаторов категорий. Затем второй раздел, который получает все продукты в этих категориях. Это гораздо более многословно, но мне нравится, как ясно, что вы видите, что происходит.
$db = new mysqli(host, user, password, database);
$all_ids = []; // total ids found, starts empty
$new_ids = [12]; // put parent ID here
do {
// master list of IDs
$all_ids = array_merge($new_ids, $all_ids);
// set up query
$set = "(".implode($new_ids, ',').")";
$sql = "select ID from categories where 'Parent ID' in $set";
// find any more parent IDs?
$new_ids = []; // reset to nothing
$rows = $db->query($sql) or die("DB error: (" . $db->errno . ") " . $db->error);
while ($row = mysqli_fetch_assoc($rows)) {
$new_ids[] = $row['ID'];
}
} while (count($new_ids) > 0);
// get products
$set = "(".implode($all_ids, ',').")";
$sql = "select * from products where 'Category ID' in $set";
$rows = $db->query($sql) or die("DB error: (" . $db->errno . ") " . $db->error);
while ($row = mysqli_fetch_assoc($rows)) {
echo "{$row['Name']}<br>\n";
}
SELECT id, имя FROM products. LEFT JOIN категории ON products.category_id = categories.id
Это может быть достигнуто с помощью соединения
SELECT id, name FROM products JOIN category ON products.category_id = categories.id WHERE products.category_id = 13 ИЛИ categories.parent_id = 12
вы можете использовать join
. ваш query
должен быть таким
SELECT
id,
name
FROM
products
JOIN
categories
ON
products.category_id = categories.id;