嵌套Set Query以检索每个节点的所有祖先

 小秋秋 发布于 2023-02-05 11:22

我有一个MySQL查询,我认为它可以很好地检索每个节点的所有祖先,从顶部节点开始,直到它的直接节点.但是当我在嵌套集中添加第5级时,它就破了.

下面是示例表,查询和SQL Fiddles:

四级嵌套集:

CREATE TABLE Tree
(title varchar(20) PRIMARY KEY,
 `tree` int,
 `left` int,
 `right` int);

INSERT Tree
VALUES
("Food", 1, 1, 18),
('Fruit', 1, 2, 11),
('Red', 1, 3, 6),
('Cherry', 1, 4, 5),
('Yellow', 1, 7, 10),
('Banana', 1, 8, 9),
('Meat', 1, 12, 17),
('Beef', 1, 13, 14),
('Pork', 1, 15, 16);

查询:

SELECT t0.title node
      ,(SELECT GROUP_CONCAT(t2.title)
                    FROM Tree t2
                    WHERE t2.leftt0.right
                    ORDER BY t2.left) ancestors
FROM Tree t0
GROUP BY t0.title;

节点的返回结果BananaFood,Fruit,Yellow- Perfect.你可以在这里看到SQL Fiddle - 4 Levels

当我在下面的5级表上运行相同的查询时,第5级节点以错误的顺序返回:

CREATE TABLE Tree
(title varchar(20) PRIMARY KEY,
 `tree` int,
 `left` int,
 `right` int);

INSERT Tree
VALUES
("Food", 1, 1, 24),
('Fruit', 1, 2, 13),
('Red', 1, 3, 8),
('Cherry', 1, 4, 7),
('Cherry_pie', 1, 5, 6),
('Yellow', 1, 9, 12),
('Banana', 1, 10, 11),
('Meat', 1, 14, 23),
('Beef', 1, 15, 16),
('Pork', 1, 17, 22),
('Bacon', 1, 18, 21),
('Bacon_Sandwich', 1, 19, 20);

返回的结果为Bacon_SandwichBacon,Food,Meat,Pork这是不正确的顺序应该是Food,Meat,Pork,Bacon-你可以看到这个在这里SQL小提琴- 5档

我不确定发生了什么,因为我不太了解子查询.任何人都可以对此有所了解吗?

调查后编辑:

哇!!看起来写出这一切并阅读订购,GROUP_CONCAT给了我一些灵感.

添加ORDER BY到实际GROUP_CONCAT函数并从子查询的末尾删除解决了该问题.我现在收到Food,Meat,Pork,Bacon节点Bacon_Sandwich

SELECT t0.title node
      ,(SELECT GROUP_CONCAT(t2.title ORDER BY t2.left)
                    FROM Tree t2
                    WHERE t2.leftt0.right
                    ) ancestors
FROM Tree t0
GROUP BY t0.title;

我仍然不知道为什么.在ORDER BY子查询结束时工作4级但不是5级?!?!

如果有人可以解释问题是什么以及为什么要ORDER BY修复它,我将非常感激.

1 个回答
  • 首先,了解您有一个隐含的重要性GROUP BY

    如果在不包含GROUP BY子句的语句中使用组函数,则它等效于对所有行进行分组.

    为了使这一点更容易理解,我将省略子查询并将问题减少到香蕉.香蕉是集[10,11].正确排序的祖先是:

    SELECT "banana" as node, GROUP_CONCAT(title ORDER by `left`)
      FROM Tree WHERE `left` < 10 AND `right` > 11
      GROUP BY node;
    

    ORDER BY必须是GROUP_CONCAT()只要你想聚合函数进行排序.ORDER BY外部按汇总结果排序(即结果GROUP_CONCAT()).直到4级工作的事实才是运气.ORDER BY对聚合函数没有影响.无论是否有ORDER BY以下结果,您都会获得相同的结果:

    SELECT GROUP_CONCAT(title)
      FROM Tree WHERE `left` < 10 AND `right` > 11
      /* ORDER BY `left` */
    

    它可能有助于理解 SELECT GROUP_CONCAT(title ORDER BY left) FROM Tree WHERE … ORDER BY left它的作用:

      获取一个选择(WHERE),它以未定义的顺序产生三行:

      ("Food")
      ("Yellow")
      ("Fruit")
      

      将结果聚合为一行(隐式GROUP BY)以便能够使用聚合函数:

      (("Food","Yellow", "Fruit"))
      

      在其上触发聚合函数(GROUP_CONCAT(title, ORDER BY link)).即按顺序排序然后连接:

      ("Food,Fruit,Yellow")
      

      现在终于对结果进行了排序(ORDER BY).因为它只有一行,所以排序不会改变.

      ("Food,Fruit,Yellow")
      

    2023-02-05 11:26 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有