【问题标题】:MySQL: Category Tree and Products in n levelsMySQL:n 级的类别树和产品
【发布时间】:2015-01-23 04:37:13
【问题描述】:

所以,假设我有一个包含以下表格的 MySQL 数据库:

产品

  • 身份证
  • 姓名
  • category_id

类别

  • 身份证
  • 姓名
  • parent_id

为了让所有产品从某个类别 ID 下降,查询数据库的最佳方法是什么。例如,如果我有一个子类别树,其中基本类别 id = 1 我如何获得 id =1 子类别下的所有产品,以获得未确定数量的子类别。

我可以这样做:

SELECT * FROM `Product` WHERE category_id IN (
   SELECT `id` FROM `Category` WHERE parent_id = 1
)

但它仅适用于类别 id = 1 的直接子代,不适用于第 2 到第 n 级子代。

谢谢。


编辑

有人建议阅读a blog article关于这个,我过去也看过那篇文章,我做了这个sqlfiddle:

http://sqlfiddle.com/#!2/be72ec/1

正如您在查询中看到的那样,即使是他们教授的最简单的方法,获取类别树也不会输出任何内容。我错过了什么?其他方法也有同样的问题。

谢谢。

【问题讨论】:

  • 看看这篇文章“MySQL中的分层数据:一个查询中的父母和孩子”:explainextended.com/2009/07/20/…。我想它可以回答你的问题。
  • @stefan 我过去曾尝试过这些帖子,但由于某种原因,它们没有返回任何数据……而且 cmets 上还有其他人也说他有同样的问题。跨度>
  • @stefan 请检查我的编辑...

标签: mysql query-optimization hierarchical-data


【解决方案1】:

我看了你的sqlfiddle,得出了以下结论。

您的代码的问题是,您使用的是 NULL 值。 查看这个 sqlfiddle 以查看一个工作示例:http://sqlfiddle.com/#!2/07ef7/1/0

我对您的陈述进行了一些更正,现在一切正常。
这是我所做的更改的列表:

  • 在 create 语句中将“parent_id bigint(11) unsigned DEFAULT NULL”更改为“parent_id bigint(11) unsigned NOT NULL DEFAULT 0”
  • 删除外键约束,但我没有让它使用“0”作为 parent_id
  • 插入“0”而不是“NULL”作为 parent_id
  • 在 FUNCTION 中将数据类型 INT 更改为 BIGINT,因为您在创建语句中使用此类型
  • 从 select 语句中删除 WHERE 子句

希望对你有帮助!

这里是语句,以防 sqlfiddle 现在不工作:

CREATE TABLE `Category` (
  `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL,
  `parent_id` bigint(11) unsigned NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  KEY `parent_id` (`parent_id`),
  KEY `ix_hierarchy_parent` (`parent_id`, `id`)
)//


INSERT INTO `Category` (`id`, `name`, `parent_id`)
VALUES
    (1,'Cat Name 1',0),
    (2,'Cat Name 2',0),
    (3,'Cat Name 3',2),
    (4,'Cat Name 4',2),
    (7,'Cat Name 5',4),
    (8,'Cat Name 6',4),
    (9,'Cat Name 7',4),
    (10,'Cat Name 8',4),
    (11,'Cat Name 9',4),
    (12,'Cat Name 10',4),
    (13,'Cat Name 11',2),
    (16,'Cat Name 12',13),
    (17,'Cat Name 13',13),
    (18,'Cat Name 14',13),
    (19,'Cat Name 15',13),
    (20,'Cat Name 16',13),
    (21,'Cat Name 17',13)//


CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_id(value BIGINT) RETURNS INT
NOT DETERMINISTIC
READS SQL DATA
BEGIN
        DECLARE _id BIGINT;
        DECLARE _parent_id BIGINT;
        DECLARE _next BIGINT;
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL;

        SET _parent_id = @id;
        SET _id = -1;

        IF @id IS NULL THEN
                RETURN NULL;
        END IF;

        LOOP
                SELECT  MIN(id)
                INTO    @id
                FROM    `Category`
                WHERE   parent_id = _parent_id
                        AND id > _id;
                IF @id IS NOT NULL OR _parent_id = @start_with THEN
                        SET @level = @level + 1;
                        RETURN @id;
                END IF;
                SET @level := @level - 1;
                SELECT  id, parent_id
                INTO    _id, _parent_id
                FROM    `Category`
                WHERE   id = _parent_id;
        END LOOP;       
END//

SELECT  CONCAT(REPEAT('    ', level - 1), CAST(hi.id AS CHAR)) AS treeitem, hi.name, parent_id, level
FROM    (
        SELECT  hierarchy_connect_by_parent_eq_prior_id(id) AS id, @level AS level
        FROM    (
                SELECT  @start_with := 0,
                        @id := @start_with,
                        @level := 0
                ) vars, `Category`
        WHERE   @id IS NOT NULL
        ) ho
JOIN    `Category` hi
ON      hi.id = ho.id

【讨论】:

  • 它确实有效,但是具有 null 值的东西只是让 fk 约束适用于基本类别的一种方式。如果我将parent_id默认设置为0,由于fk,它将无法工作。
猜你喜欢
  • 1970-01-01
  • 2018-01-23
  • 2019-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多