用于层次关系的SQL

时间:2012-07-08 11:42:12

标签: mysql sql

我有一个表格,根据树状结构等层次关系对产品进行分类。我必须在任何级别选择一个类别和所有子类别。见下图:

enter image description here

e.g。我想要一个sql语句,当我查询传递id = 11时,它返回我(19,20,21,22,23,24,25,26)

4 个答案:

答案 0 :(得分:9)

在MySQL中存储多种不同的方法来存储分层数据。查看Bill Karwin的presentation,其中有四个选项。

  • 邻接清单
  • 路径枚举
  • 嵌套集
  • 关闭表

您正在使用邻接列表模型来存储层次数据,但不幸的是,这是您可以选择查询子树的最难模型。

nested sets query subtree

您的选择是:

  • 更改为其他型号。
  • 将查询限制为n级深度。
  • 使用存储过程递归查询。有关此内容的更多信息,请参阅Quassnoi的系列文章 - Hierarchical queries in MySQL

答案 1 :(得分:1)

SELECT * FROM `Products` 
WHERE parentId IN (
    SELECT id FROM `Products` 
    WHERE parentId = 11)

注意:如果您的层次结构超过2个级别,则无效。

答案 2 :(得分:1)

您是否可以稍微更改数据结构以包含计算的linage列。有great article,它显示了通用概念(忽略数据库类型)。

基本上,您计算的linage列应包含其中的父项列表,例如

第26项将包含\11\

如果你有一个子项目,你可以

\11\subitem\

然后你可以简单地对你的linage表进行检查,它比迭代搜索快得多,你可以使用存储的proc或触发器来创建它。

Node    ParentNode  EmployeeID  Depth   Lineage
100        NULL         1001            0   /
101        100          1002            1   /100/
102        101          1003            2   /100/101/
103        102          1004            3   /100/101/102/
104        102          1005            3   /100/101/102/
105        102          1006            3   /100/101/102/

答案 3 :(得分:0)

这很麻烦,你必须在工会中做,其中n是层次结构的深度,但它应该有效:

SELECT * FROM `Products` WHERE parentId IN (
    SELECT id FROM `Products` WHERE parentId = 11)
UNION
SELECT * FROM `Products` WHERE parentId IN (
    SELECT id FROM `Products` WHERE parentId IN (
         SELECT id FROM `Products` WHERE parentId = 11))
UNION
SELECT * FROM `Products` WHERE parentId IN (
    SELECT id FROM `Products` WHERE parentId IN (
        SELECT id FROM `Products` WHERE parentId IN (
             SELECT id FROM `Products` WHERE parentId = 11)))