Php 用于从父类别检索子类别中存储的项的数据库体系结构

Php 用于从父类别检索子类别中存储的项的数据库体系结构,php,mysql,data-structures,hierarchy,Php,Mysql,Data Structures,Hierarchy,未能找到问题的解决方案,我想知道是否有更好的方法来存储此问题的数据 这种数据库结构允许将项目存储在多个类别中,但不允许轻松访问父类别层次结构 我希望有一个类别关系,例如: Books > Novels > Paperbacks > Hardbacks 例如,有一个项目存储在平装本上,它也会出现在小说和书籍中。因此,“类别”实际上更像过滤器,而不是实际的类别。首先,您需要使用体系结构设计类别表。通过使用嵌套集,您可以轻松地选择类别的整个分支,然后可以为这些

未能找到问题的解决方案,我想知道是否有更好的方法来存储此问题的数据

这种数据库结构允许将项目存储在多个类别中,但不允许轻松访问父类别层次结构

我希望有一个类别关系,例如:

Books 
  > Novels
    > Paperbacks
    > Hardbacks

例如,有一个项目存储在平装本上,它也会出现在小说和书籍中。因此,“类别”实际上更像过滤器,而不是实际的类别。

首先,您需要使用体系结构设计类别表。通过使用嵌套集,您可以轻松地选择类别的整个分支,然后可以为这些类别选择产品

因此,第一个表将是:

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)
);
第二个表格是:

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)
);
第三个表格是:

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
第二步:插入新类别

INSERT INTO categories SET left = @right, right = @right + 1, name = @name
删除现有节点

第一步:删除节点

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

一个很好的方法是存储“左”和“右”相关的类别id,而不是单一的父类id。“顶级”类别是选择的少数没有左侧关系的类别,每个链可以通过添加更多右侧关系继续深入。回答不错,但用新类别更新类别树可能是一个噩梦。这不是噩梦,你需要实现一次,它会很好地工作。我已经更新了答案并添加了查询以添加和删除节点。