Que tipo de estrutura DB devo usar para um site tem infinita sub-categoria?
-
07-07-2019 - |
Pergunta
Por exemplo, "Dole Banana" é um tipo de produto, que está listada na categoria "Bananas", quando eu abrir a categoria "Frutas", eu quero ver "Dole Banana".
+ Food
|--+ Fruits
|------+ Bananas
|------+ Apples
|--+ Vegetables
|------+ Onion
|------+ Spinach
Solução
Eu normalmente usado árvores esquerda-direita que são muito bem adaptado para querys de banco de dados. Você tem um parentId, esquerda e direita valor para cada nó. Cada nós filhos tem um valor esquerda / direita que está entre os nós pai esquerda e direita que o torna muito fácil de encontrar, por exemplo, todas as crianças / pais de um nó. Ele dá uma ligeira sobrecarga de inserções, mas não deve ser demasiado de um impacto a menos que você insira um monte.
Edit: Apenas uma palavra de advertência, porém, que você precisa para tornar as operações insert / update em uma transação bloqueado ou a árvore pode ficar confuso
.Outras dicas
Se você está procurando recursos on-line que tratam desse problema, "Armazenamento de uma árvore em um banco de dados" seria uma frase boa pesquisa.
Como para a solução, nota que cada subcategoria pode ter um ou zero de categorias pai. Portanto, a árvore inteira pode ser armazenada em uma única tabela auto-refferental com um campo de "pai".
Usando o exemplo da árvore:
ID | PARENT | NAME
-----+--------+-------------
1 | null | Food
2 | 1 | Fruits
3 | 2 | Bananas
4 | 2 | Apples
5 | 1 | Vegetables
6 | 5 | Onion
7 | 5 | Spinach
A tabela "Categorias" com 3 campos.
- CategoryId não nula (chave primária)
- ParentCategoryId nulo
- NomeDaCategoria not null
Para obter todas as categorias raiz
select * from Categories where ParentCategoryId is null
Para obter todas as categorias sub de alguma categoria específica:
select * from Categories where ParentCategoryId = 12
Você pode usar a estrutura da tabela simples com parent_category_id e recuperar árvore inteira com recursividade ou implementar valores Esquerdo / Direito e buscar árvore inteira usando o método de passagem de árvore pre-ordenado.
Se você quer dizer um número infinito de níveis, em seguida, uma referência a auto tabela que pode ser recursed. Exemplo: StuffID, StuffName, StuffParentID (FK para material ID)
Para um número finito, tabelas fixas: pai-filho-neto
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
Para hierarquia infinita, use o árvore preorder modificado travessia algoritmo
Aqui está uma abordagem diferente, que pode ser útil para você. Ele tem um pouco mais os custos de manutenção do que a PARENT_ID ou LFT abordagem / rght, mas a recuperação é muito mais fácil (e mais rápido).
bananas Dole pode ser na tabela produtos. Você tem um único category_id para um produto.
Nós tivemos um requisito para permitir que várias categorias para um produto. Isso nos levar a ter um categories_products juntar a mesa, onde o produto pode ter várias linhas unidas. Então, tivemos que decidir se quer ter bananas Dole em apenas bananas, ou em bananas e todos os seus pais também. Como velocidade de recuperação era crítica, nós colocamos distribuir bananas em suas categorias e todas as suas categorias pai. Há três categoria-produto se junta para bananas Dole.
Usando essa estrutura, retornando todos os itens a partir de qualquer categoria é fácil e rápido, apenas uma consulta. Você não pode fazer isso na abordagem PARENT_ID (a menos que os pais de código duro, avós, etc.) Adição de uma categoria é fácil. Categorizar um produto requer a inserção de várias linhas na tabela de junção. Excluindo e movendo categorias são um pouco mais complicado.