Take the 2-minute tour ×
Database Administrators Stack Exchange is a question and answer site for database professionals who wish to improve their database skills and learn from others in the community. It's 100% free, no registration required.

I am making a ecommerce site. In this site I want to categorise the items into three different layers

primary category             sub category           sub category

>>electronic             >>smart phone          samsung
  cameras                       tablets              nokia  
                                laptop               apple
                                headphone

In the above table, I want to display the sub category after the customer selects the primary one. At the same time the 'samsung' also comes under 'camera'. Like this a parent can have any number of children and one child can have many parents. In the future we may change the primary and secondary.

What is the best solution for this? Which model will adopt our category: tree or nested?

share|improve this question
    
It's not clear what you want. Can an item belong to 2 sub-sub-categories, like both "nokia" and "apple"? Can an item belong to 2 (different level) categories, like "laptop" and "nokia"? Or is any item related (belongs to) one and only one category or sub-category? –  ypercube Feb 23 '13 at 21:30
    
For the categories, are there exactly 3 levels as you show and no more? And can a category belong to different level (as in your example, "samsung" is in level-3 under "smart phone", and in level-2 under "camera")?. –  ypercube Feb 23 '13 at 21:33

2 Answers 2

I want to expand Neil's point above by showing what a hierarchical query would look like in PostgreSQL. I will also concur that this is a significant weak point in MySQL because recursive queries are not supported.

Suppose we want to traverse upwards from product to see the full classification. The query would look like:

WITH RECURSIVE product_chain (id, path, parent_id, category_name) AS (
   SELECT c.id, c.name, parent_id, c.name
     FROM category 
    WHERE id in (SELECT category_id FROM product_category 
                  WHERE product_id = 1)
UNION ALL
   SELECT c.id, c.name || '/' || pc.path, c.parent_id, c.name
     FROM category 
     JOIN product_chain pc ON pc.parent_id = c.id
 )
 SELECT p.*, pc.path
   FROM product p
   JOIN product_chain pc ON pc.parent_id IS NULL
  WHERE p.id = 1;

Similarly we can generate the entire category tree with something like:

WITH RECURSIVE cat_tree (id, level, path) AS (
   SELECT c.id, 1, c.name
     FROM category c WHERE parent_id IS NULL
UNION ALL
   SELECT c.id, ct.level + 1, ct.path || '/' || c.name
     FROM category c
     JOIN cat_tree ct ON c.parent_id = ct.id
 )
 select c.name, ct.path, ct.level
   FROM category c
   JOIN cat_tree ct ON c.id = ct.id;

Both of these perform remarkably well on PostgreSQL.

share|improve this answer

You should consider Postgres, as it does hierarchical querying better than Mysql. If using Mysql, consider using a closure table to aid querying.

I think you are actually confusing Brand and sub-sub-category. You should have a brand table too.

create table category (
  id serial primary key,
  name text not null,
  parent_id int null references category(id)
);


create table brand (
  id serial primary key,
  name text not null unique
);


create table brand_category (
  brand_id int not null references brand(id),
  category_id int not null references category(id),
  primary key (brand_id, category_id)
);


/* the product specification, not the actual product asset instance: */
create table product (
  id serial primary key,
  name text not null,
  brand_id int not null references brand(id)
);


create table product_category (
  product_id int not null references product(id),
  category_id int not null references category(id),
  primary key (product_id, category_id)
);

example:

/* null parent_id means top-level category */
insert into category values

(1, 'Electronics', null),
(2, 'Cameras', null),

(3, 'Smart Phones', 1),
(4, 'Tablets', 1),
(5, 'Laptops', 1),
(6, 'Headphones', 1);


insert into brand values 
(1, 'Samsung'),
(2, 'Nokia'),
(3, 'Apple');


/* samsung brand in both smartphones and cameras: */
insert into brand_category values
(1, 3),
(1, 2),
(2, 3),
(3, 3);


insert into product values 
(1, 'Samsung Model X', 1);


/* add samsung model x as a smart phone: */
insert into product_category values
(1, 3);
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.