微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

php – 如何在分层类别树中找到我的节点及其anchestors的所有兄弟姐妹?

这是我的表:

CREATE TABLE IF NOT EXISTS  `Category` (
`Name` varchar(25) NOT NULL,
`lft` INT UNSIGNED NOT NULL,
`rgt` INT UNSIGNED NOT NULL,
`CategoryId` int UNSIGNED auto_increment NOT NULL,
PRIMARY KEY (`CategoryId`)
) Engine = InnoDb;

我有一个看起来像这样的网址:products.PHP?category = 5

从类别ID我需要在层次结构的每个级别检索具有相同父级的所有类别.我找到了一种方法来做到这一点,但我认为这是低效的,有没有更好的方法来做到这一点?

CREATE VIEW category_tree AS
SELECT node.name as name,
    node.categoryId as categoryId,
    node.lft as lft,
    node.rgt as rgt,
    (COUNT(parent.categoryId) - 1) AS depth
FROM Category AS node,
Category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
GROUP BY node.categoryId;

SELECT tree.name, tree.depth, tree.categoryId,
(node.lft BETWEEN tree.lft AND tree.rgt) AS is_selected
FROM category_tree as tree
JOIN category_tree AS node ON node.categoryId = :selectedCategory
JOIN (
    SELECT MAX(tree.lft) as lft
    FROM category_tree as tree
    JOIN category_tree AS node ON node.categoryId = :selectedCategory
    WHERE
    tree.depth = node.depth -1
    AND tree.lft < node.lft
) AS parent_finder
LEFT JOIN category_tree AS parent ON parent.lft = parent_finder.lft
WHERE tree.depth < node.depth
OR (
  tree.depth = node.depth
  AND tree.lft BETWEEN parent.lft AND parent.rgt
)
OR (
  tree.lft BETWEEN node.lft AND node.rgt
  AND tree.depth <= node.depth + 1
)
ORDER BY tree.depth, tree.name

例如,假设我的类别树如下所示:

http://dev.mysql.com/tech-resources/articles/hierarchical-data-1.png
(自Managing Hierarchical Data in MySQL起)

假设用户选择了“cd player”,我想检索以下信息:

name                 depth    is_selected
electronics           0            1
portable electronics  1            1
televisions           1            0
mp3 players           2            0
cd players            2            1
2 way radios          2            0

我想检索所有选定的类别以及与所选类别处于同一级别的所有类别以及深度信息和选择的类别.

我需要这样做的原因是,产品页面可以包含下拉到所选类别的每个级别的下拉导航菜单.

解决方法:

我不确定我是否遵循了这一切,但听起来你想要所有直接的5类孩子.

这是一种方法

SELECT child.*
FROM Category parent
  JOIN Category child 
    ON (child.lft BETWEEN parent.lft AND parent.rgt)
  LEFT JOIN Category intermediate 
    ON (intermediate.lft > parent.lft AND intermediate.rgt < parent.rgt
      AND child.lft > intermediate.lft AND child.rgt < intermediate.rgt)
WHERE intermediate.CategoryId IS NULL
  AND parent.CategoryId = ?;

编辑:好的,我现在明白上面的解决方案只是你想要的一部分.你要:

>直接CD播放器的祖先
> CD播放器的“叔叔”(祖先的兄弟姐妹)
> CD播放器的兄弟姐妹
> CD播放器的儿童

让我继续研究几分钟.

这是我想出的:

SELECT descendant.*,
  (current.lft BETWEEN descendant.lft AND descendant.rgt) AS is_selected,
  COUNT(disTINCT c.CategoryId) AS depth
FROM Category current
JOIN Category selected 
  ON (current.lft BETWEEN selected.lft AND selected.rgt)
JOIN Category descendant 
  ON (descendant.lft BETWEEN selected.lft AND selected.rgt)
LEFT JOIN Category intermediate 
  ON (intermediate.lft > selected.lft AND intermediate.rgt < selected.rgt
    AND descendant.lft > intermediate.lft AND descendant.lft < intermediate.rgt)
JOIN Category c
  ON (descendant.lft BETWEEN c.lft AND c.rgt)
WHERE intermediate.CategoryId IS NULL
  AND current.CategoryId = ?
GROUP BY descendant.CategoryId
ORDER BY depth, descendant.name;

>目前是CD播放器
>精选CD播放器(电子产品,便携式电子产品,CD播放器)的祖先
>后代是每个选定祖先的子孙或孙子等
> intermediate是每个选定祖先的后代,也是后代的父级 – 必须没有这些,因此IS NULL限制.
> c是从后代回到顶部的祖先链,用于确定深度.

我刚刚意识到我的解决方案也将返回当前节点的所有后代.因此,如果您当前正在查看“便携式电子产品”,则查询将返回其子项,但它也会返回孙子“闪存”,这可能不是您想要的.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐