Архитектура БД для извлечения элементов, хранящихся в дочерних категориях, из родительских категорий - PullRequest
0 голосов
/ 09 декабря 2011

Не удалось найти решение этого вопроса. Мне было интересно, есть ли лучший способ хранения данных для этой проблемы.

Эта структура БД позволяет хранить элементы в нескольких категориях., но не разрешает легкий доступ к иерархии родительских категорий.

Я хотел бы иметь отношение к категории, например:

Books 
  > Novels
    > Paperbacks
    > Hardbacks

, и иметь элемент, сохраненный в мягкой обложке дляЭкземпляр, который также будет показан в романах и книгах.Таким образом, «категории» на самом деле работают больше как фильтры, чем как настоящие категории.

1 Ответ

2 голосов
/ 09 декабря 2011

Прежде всего вам необходимо создать таблицу категорий с использованием архитектуры Nested Set .С использованием Nested Sets вы легко выберете целую ветвь категорий, а затем сможете выбирать товары для этих категорий.

Итак, первая таблица будет:

CREATE TABLE categories (
  id int unsigned NOT NULL auto_increment,
  name varchar(255) NOT NULL,
  left int unsigned NOT NULL,
  right int unsigned NOT NULL,
  PRIMARY KEY (id)
);

.вторая таблица будет:

CREATE TABLE products (
  id int unsigned NOT NULL auto_increment,
  name varchar(255) NOT NULL,
  PRIMARY KEY (id)
);

И третья таблица будет:

CREATE TABLE product_categories (
  category_id int unsigned NOT NULL,
  product_id int unsigned NOT NULL,
  PRIMARY KEY (category_id, product_id)
);

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

SELECT p.*
  FROM categories AS c1
  LEFT JOIN categories AS c2 ON c1.left <= c2.left AND c2.right <= c1.right
  LEFT JOIN product_categories AS pc ON pc.category_id = c2.id
  LEFT JOIN products AS p ON pc.product_id = p.id
 WHERE c1.id = @id

Операции с вложенными множествами

Добавить новый узел

1-й шаг: обновить уже существующие категории

UPDATE categories 
   SET right = right + 2, left = IF(left > @right, left + 2, left) 
 WHERE right >= @right

2-й шаг: вставить новую категорию

INSERT INTO categories SET left = @right, right = @right + 1, name = @name

Удалить существующий узел

1-й шаг: удалить узел

DELETE FROM categories WHERE left >= @left AND right <= @right

2-й шаг: обновить остальные узлы

UPDATE categories 
   SET left = IF(left > @left, left – (@right - @left + 1), left), 
       right = right – (@right - @left + 1) 
 WHERE right > @right
...