Как получить статьи определенной категории и ее детей?
Я разрабатываю систему статей, в которой используются категории и дочерние категории.
В принципе, если категория имеет значение parent_id
, это дочерний элемент этой категории.
Я хотел бы иметь возможность получать последние статьи из категории и статей из своих дочерних категорий.
Например: у меня есть категория под названием "Игровые статьи" и несколько дочерних категорий под названием Xbox, PlayStation, Nintendo и ПК. Моя система позволяет размещать статьи в родительских категориях, таких как игровые статьи, а также в дочерних категориях.
Таким образом, это должно включать статьи, которые находятся либо в родительской категории, либо в дочерних категориях этого родителя.
CREATE TABLE IF NOT EXISTS `articles` (
`article_id` int(15) NOT NULL AUTO_INCREMENT,
`author_id` int(15) NOT NULL,
`category_id` int(15) NOT NULL,
`modification_id` int(15) NOT NULL,
`title` varchar(125) NOT NULL,
`content` text NOT NULL,
`date_posted` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`status` tinyint(1) NOT NULL,
`attachment_id` int(15) NOT NULL,
PRIMARY KEY (`article_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `article_categories` (
`category_id` int(15) NOT NULL AUTO_INCREMENT,
`parent_id` int(15) NOT NULL,
`title` varchar(50) NOT NULL,
`description` text NOT NULL,
`attachment_id` text NOT NULL,
`enable_comments` tinyint(1) NOT NULL,
`enable_ratings` tinyint(1) NOT NULL,
PRIMARY KEY (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Запрос, который у меня есть до сих пор...
SELECT article_id, category_id
FROM articles
WHERE category_id = 1
ORDER BY article_id DESC
LIMIT 10
Конечно, это получает только статьи под этой категорией, а не как дочерние категории категории, так и категории.
Ответы
Ответ 1
По мере того, как ваша структура таблицы стоит, этот запрос будет работать, если предполагается только один уровень вложенности (т.е. дети сами не имеют детей):
SELECT a.*
FROM articles a
JOIN article_categories ac ON a.category_id = ac.category_id
WHERE 1 IN (a.category_id, ac.parent_id)
ORDER BY a.article_id DESC
LIMIT 10
Обратите внимание на стиль "reverse" IN
, чтобы аккуратно захватить то, что эффективно является OR
.
Если ваша вложенность глубже, просто добавьте другое соединение для каждого уровня, например, если у вас есть до 4 уровней (на 2 больше, чем выше):
SELECT a.*
FROM articles a
JOIN article_categories ac1 ON a.category_id = ac1.category_id
LEFT JOIN article_categories ac2 ON ac1.parent_id = ac2.category_id
LEFT JOIN article_categories ac3 ON ac2.parent_id = ac3.category_id
WHERE 1 IN (a.category_id, ac1.parent_id, ac2.parent_id, ac3.parent_id
ORDER BY a.article_id DESC
LIMIT 10
Во втором случае использование левых объединений необходимо для возврата статей, которые не имеют так много уровней выше.
Ответ 2
В этой структуре она невозможна в одном запросе. (Я предполагаю, что существует много уровней категорий)
Вы можете:
-
рекурсивно искать дочерние категории (например, в php), а затем
SELECT * FROM articles WHERE category_id IN ($ categories);
-
изменить структуру db и использовать древовидную структуру
try: Вложенная модель набора в статье: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
-
добавить новую таблицу в таблицу категорий и сохранить полный путь к категории, например:
категория 1- > 2, category_path 1,2
категория 1- > 2- > 3, category_path 1,2,3
категория 1- > 4, новая категория_path 1,4
Если вы ищете все данные категории 1 и детей, попробуйте:
SELECT
a.*
FROM articles a
INNER JOIN categories c
ON a.category_id = c.category_id
WHERE c.category_path LIKE '1,%'
Ответ 3
Насколько я понимаю, вы хотите получить все статьи от ребенка категории, если это правильно, попробуйте это:
SELECT a.article_id, a.category_id FROM articles as a, article_categories c WHERE a.category_id = c.category_id AND c.parent_id = (SELECT c.parent_id WHERE c.category_id = 1) ORDER BY article_id DESC LIMIT 10
Если это не то, что вы хотели, прокомментируйте это, я постараюсь ответить вам.