Nested Set Query to retrieve all ancestors of each node

后端 未结 2 1569
执念已碎
执念已碎 2021-02-06 07:44

I have a MySQL query that I thought was working fine to retrieve all the ancestors of each node, starting from the top node, down to its immediate node. However when I added a 5

2条回答
  •  长发绾君心
    2021-02-06 08:26

    First it's important to understand that you have an implicit GROUP BY

    If you use a group function in a statement containing no GROUP BY clause, it is equivalent to grouping on all rows.

    To make the point more understandable I'll leave out subqueries and reduce the problem to the banana. Banana is the set [10, 11]. The correct sorted ancestors are those:

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

    The ORDER BY must be in GROUP_CONCAT() as you want the aggregation function to sort. ORDER BY outside sorts by the aggregated results (i.e. the result of GROUP_CONCAT()). The fact that it worked until level 4 is just luck. ORDER BY has no effect on an aggregate function. You would get the same results with or without the ORDER BY:

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

    It might help to understand what SELECT GROUP_CONCAT(title ORDER BY left) FROM Tree WHERE … ORDER BY left does:

    1. Get a selection (WHERE) which results in three rows in an undefined order:

      ("Food")
      ("Yellow")
      ("Fruit")
      
    2. Aggregate the result into one row (implicit GROUP BY) in order to be able to use an aggregate function:

      (("Food","Yellow", "Fruit"))
      
    3. Fire the aggregate function (GROUP_CONCAT(title, ORDER BY link)) on it. I.e. order by link and then concatenate:

      ("Food,Fruit,Yellow")
      
    4. And now finally it sorts that result (ORDER BY). As it's only one row, sorting changes nothing.

      ("Food,Fruit,Yellow")
      

提交回复
热议问题