Какую структуру БД я должен использовать для сайта с бесконечной подкатегорией?

StackOverflow https://stackoverflow.com/questions/1418160

Вопрос

Например, «Dole Banana» это тип продукта, он указан в разделе "Бананы" категории, когда я открываю "Фрукты" категорию, я хочу увидеть "Dole Banana".

+ Food
|--+ Fruits
|------+ Bananas   
|------+ Apples
|--+ Vegetables
|------+ Onion
|------+ Spinach
Это было полезно?

Решение

Я обычно использовал деревья слева-справа , которые очень хорошо адаптированы к запросам к базе данных. У вас есть parentId, левое и правое значение для каждого узла. Каждый дочерний узел имеет левое / правое значение, которое находится между родительскими узлами слева и справа, что позволяет очень легко найти, например, всех дочерних / родительских узлов. Это немного увеличивает накладные расходы на вставку, но не должно быть слишком сильным, если вы не вставите много.

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

Другие советы

Если вы ищете онлайн-ресурсы, посвященные этой проблеме, " Хранение дерева в базе данных " будет хорошей поисковой фразой.

Что касается решения, обратите внимание, что каждая подкатегория может иметь одну или нулевую родительскую категорию. Следовательно, все дерево может быть сохранено в одной само-ссылочной таблице с «родителем». поле.

Используя ваше дерево примеров:

 ID  | PARENT | NAME
-----+--------+-------------
  1  |  null  | Food
  2  |   1    | Fruits
  3  |   2    | Bananas
  4  |   2    | Apples
  5  |   1    | Vegetables
  6  |   5    | Onion
  7  |   5    | Spinach

Таблица "Категории" с 3 полями. <Ол>

  • CategoryId не нулевой (первичный ключ)
  • ParentCategoryId null
  • CategoryName not null
  • Чтобы получить все корневые категории

    select * from Categories where ParentCategoryId is null
    

    Чтобы получить все подкатегории определенной категории:

    select * from Categories where ParentCategoryId = 12
    

    Вы можете использовать простую структуру таблицы с parent_category_id и извлекать все дерево с помощью рекурсии или реализовывать левые / правые значения и извлекать все дерево, используя предварительно упорядоченный метод обхода дерева.

    Если вы имеете в виду бесконечное количество уровней, то таблицу с самореференциями можно использовать повторно. Пример: StuffID, StuffName, StuffParentID (от FK до Stuff ID)

    Для конечного числа фиксированные таблицы: parent-child-grandchild

        CREATE TABLE [dbo].[Category](
        [CategoryId] [int] NOT NULL,
        [ParentCategoryId] [int] NULL,
        [CategoryName] [nvarchar](50) NOT NULL,
         CONSTRAINT [PK_Category] PRIMARY KEY CLUSTERED 
        (
            [CategoryId] ASC
        )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
        ) ON 
    
    [PRIMARY]
    
    GO
    
    ALTER TABLE [dbo].[Category]  WITH CHECK ADD  CONSTRAINT [FK_Category_Category] FOREIGN KEY([ParentCategoryId])
    REFERENCES [dbo].[Category] ([CategoryId])
    GO
    
    ALTER TABLE [dbo].[Category] CHECK CONSTRAINT [FK_Category_Category]
    GO
    

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

    Вот другой подход, который может быть полезен для вас. У него немного больше затрат на обслуживание, чем у подхода PARENT_ID или lft / rght, но поиск намного проще (и быстрее).

    Dole бананы могут быть в таблице продуктов. У вас есть один category_id для продукта.

    У нас было требование разрешить несколько категорий для продукта. Это привело нас к созданию таблицы соединений category_products, где продукт может иметь несколько соединенных строк Затем мы должны были решить, есть ли бананы Dole только в бананах, или в бананах и всех их родителях. Поскольку скорость поиска была критической, мы поместили бананы пособия по безработице в его категории и все их родительские категории. Есть три объединения продуктов категории для бананов пособия по безработице.

    Используя эту структуру, вернуть все элементы из любой категории легко и быстро, всего один запрос. Вы не можете сделать это в подходе PARENT_ID (если вы не жестко закодировали родителей, бабушек и дедушек и т. Д.). Добавить категорию просто. Категоризация продукта требует вставки нескольких строк в таблицу соединений. Удаление и перемещение категорий немного сложнее.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top