SQL-запрос для выбора продуктов из всех категорий One Parent

У меня есть таблица продуктов с такой структурой

 id, title, slug, details, category(FK category.ID)

И таблица категорий: id, name, slug, parent

Категории имеют только 1 уровень. Если родительского элемента нет, то родительское поле равно 0, в противном случае сохраняется идентификатор родительской категории.

Предположим, у меня есть такая структура категорий:

FRUITS
|---- APPLE
|---- MANGO
|---- BANANA

Я использую ярлык категории для запроса продуктов из категории

category.php? cat = яблоко category.php? cat = манго

1-й запрос:

select id,name from category WHERE slug='$catslug'

После получения идентификатора категории используйте запрос, чтобы получить результаты этого идентификатора из таблицы продуктов.

select * from products where category=$categoryid

Какой запрос требуется, если я хочу получить все товары, размещенные в FRUITS?

category.php?cat=fruits

Я хочу, чтобы все продукты были размещены в яблоках, манго, бананах (все дети фруктов)

В таблице продуктов сохраняются только дочерние идентификаторы. Как связать с ними яблоко родительской категории?


person Vehlad    schedule 27.03.2012    source источник
comment
Сколько у вас уровней категорий? Больше двух?   -  person mellamokb    schedule 27.03.2012
comment
Хранит ли родительский столбец идентификатор или имя родителя? Какую базу данных вы используете?   -  person Chetter Hummin    schedule 27.03.2012
comment
@mellamokb имеет только один уровень родитель-потомок. Если у категории есть родительский элемент, то идентификатор сохраняется в родительском поле таблицы категорий, иначе 0, что по умолчанию   -  person Vehlad    schedule 27.03.2012
comment
@AmitBhargava да идентификатор родительского кота, сохраненный в родительском поле, если родительский объект отсутствует 0 Тип БД InnoDB   -  person Vehlad    schedule 27.03.2012


Ответы (3)


Вы можете искать категории, связанные с продуктами, где родительской категорией является категория фруктов, с помощью нескольких объединений. Здесь cc относится к дочерней категории, а cp относится к родительской категории. Мы извлекаем все продукты, имеющие дочернюю категорию, равную категории продуктов, и имеющие родительскую категорию для этой дочерней категории, равную FRUITS:

    select *
      from products p
inner join categories cc on cc.category = p.category
inner join categories cp on cp.category = cc.parentcategory
     where cp.category = 'FRUITS'

Если это должно быть универсальное решение, которое беспристрастно обрабатывает как родительские, так и дочерние категории, вы можете проверить соответствие на любом уровне (при условии, что все названия категорий уникальны, и каждый продукт имеет категорию):

    select *
      from products p
inner join categories cc on cc.category = p.category
 left join categories cp on cp.category = cc.parentcategory
     where cc.category = '$category' or cp.category = '$category'
person mellamokb    schedule 27.03.2012
comment
Спасибо за помощь. Все имена не уникальны, но уникальны slug & ID Я думаю, ваше решение основано на названии категории? сохраняется только идентификатор category.parent, если нет родительского элемента, то 0 и в таблице product.category также содержит идентификатор категории, и каждый продукт должен иметь 1 категорию. - person Vehlad; 27.03.2012
comment
Я использовал второй запрос с некоторой заменой slug select * from products p Inner JOIN users u ON u.id = p.author inner join category cc on cc.id = p.category left join category cp on cp.id = cc.parent where cc.slug = '$catslug' or cp.slug = '$catslug' ORDER BY p.date DESC, но он пропускает последнюю запись, если плод родительской категории имеет 6 записей, он показывает только 5 и пропускает последнюю запись, которая является последней записью в дочерней таблице из таблицы продуктов! добавлены таблицы пользователей JOIN, также я хочу получить category.name из таблицы категорий в результате - person Vehlad; 28.03.2012
comment
да, проблема с записями решена с помощью цикла в теле, теперь нужно получить имя категории [category.name] в запросе - person Vehlad; 28.03.2012

1) Вам не нужно использовать два запроса, вы можете использовать join:

SELECT p.id, p.title, p.slug ...
FROM products p
JOIN categories c ON c.id = p.category
WHERE c.slug = 'apple'

2) Вы можете выбрать все фруктовые продукты с помощью этого запроса:

SELECT id, title, slug ...
FROM products
WHERE category IN (
  SELECT id
  FROM categories
  WHERE slug = 'fruits'
  UNION
  SELECT c.id
  FROM categories c
  JOIN categories c2 ON c2.id = c.parent
  WHERE c2.slug = 'fruits'
)
person tarmaq    schedule 27.03.2012
comment
Я использую 1-й запрос в начале страницы, чтобы получить имя кошки и катиду, затем отображать описание имени кошки в заголовке и заголовке. Затем 2-й запрос на странице с циклом, чтобы перечислить все продукты из этой категории, только идентификатор категории сохраняется в category.parent, поскольку я использую slug для получения результаты 1-й Мне нужно сопоставить ярлык категории с идентификатором? - person Vehlad; 27.03.2012
comment
Большое спасибо, что он отлично работает :), но запрос выполняется очень долго. Еще 1 вещь. Могу ли я использовать IF ELSE, то есть два разных запроса, если нет родительского запроса, чем обычный запрос без UNION - person Vehlad; 27.03.2012
comment
вы уверены, что у вас есть необходимые первичные / внешние ключи / индексы? - person tarmaq; 28.03.2012
comment
да идентификатор продукта, ярлык первичного продукта. категория FK категории .id products.author FK пользователя users.id и category.id, category.slug уникальный - person Vehlad; 28.03.2012
comment
как получить имя дочерней категории (category.name) из таблицы категорий, в которой продукт размещен с идентификатором этой дочерней категории (product.category), чтобы показать продукт под этим запросом - person Vehlad; 28.03.2012

Я использовал второй запрос, предложенный tarmaq

SELECT * 
    FROM products
    WHERE category IN (
    SELECT id
    FROM category
    WHERE slug = '$cats'
    UNION
    SELECT c.id
    FROM category c
    JOIN category c2 ON c2.id = c.parent
    WHERE c2.slug = '$cats')";

Он показывает результаты только из таблицы продуктов. Не получается имя категории, сведения о категории из таблицы категорий.

Я пробовал это:

SELECT * 
    FROM products
    WHERE category IN (
    SELECT *
    FROM category
    WHERE slug = '$cats'
    UNION
    SELECT *
    FROM category c
    JOIN category c2 ON c2.id = c.parent
    WHERE c2.slug = '$cats')";

результат: Ошибка в запросе.

также я хочу присоединиться к таблице пользователей в приведенном выше запросе и показать имя автора (users.name) вместе с продуктом (идентификатор автора, сохраненный в таблице продукта, который является FK из таблицы пользователей users.id уникален)

JOIN users on products.author = users.id

Где разместить этот оператор соединения в запросе выше

РЕДАКТИРОВАТЬ - я присоединил пользовательскую таблицу с именем автора с этим запросом

SELECT * 
FROM products
JOIN users U ON U.id = products.author
WHERE category IN (
SELECT id
FROM category
WHERE slug = '$cats'
UNION
SELECT C.id
FROM category C
JOIN category C2 ON C2.id = C.parent
WHERE C2.slug = '$cats') 
ORDER BY products.date DESC

теперь хотите получить данные из таблицы категорий catagory.name, category.details с помощью этого запроса

person Vehlad    schedule 28.03.2012