【问题标题】:Altering the order of a hierarchical result generated by a Recursive CTE?更改递归 CTE 生成的分层结果的顺序?
【发布时间】:2020-06-27 15:44:27
【问题描述】:

我正在使用 MySQL,我想知道是否可以更改递归 CTE 生成的结果的顺序。

我的表有这些列:

|----------|----------|----------|----------|
|   ID     | parentID |  title   |   Sort   |
|----------|----------|----------|----------|
|    1     |    null  |  Maria   |     1    |
|    2     |    1     |  John    |     2    |
|    3     |    2     |  Maria   |     3    |
|    4     |    1     |  Anthony |     1    |
|    5     |    4     |  XXX     |     1    |
|    6     |    4     |  ...     |     2    |
|    7     |    2     |  ...     |     2    |
|    8     |    2     |  ...     |     1    |
|    9     |    1     |  ...     |     3    |

我使用以下查询(我们不考虑排序列)

   WITH RECURSIVE cte AS
    (
      SELECT ID, parentID, title, 0 AS depth, CAST(ID AS CHAR(200)) AS path
        FROM categories WHERE ID = 1
      UNION ALL
      SELECT c.ID, c.parentID, c.title, cte.depth + 1, CONCAT(cte.path, ',', c.ID) 
        FROM categories c 
        JOIN cte ON cte.parentID = c.ID
        WHERE FIND_IN_SET(c.ID, cte.path)=0
    )
    SELECT * FROM cte ORDER BY cte.path

接下来是我们从上述查询中获得的分层结果(以 ID 为单位)。我们完全忽略了排序列。

Hierarchy Depth
1   2   3
|   |   |
IDs
1
    2
        3
        7
        8
    4
        5
        6
    9

我想要的是一个考虑sort 列并创建以下顺序的查询。从您看到的 4、2、9 的 ID 分别具有 1、2、3 的排序编号,并且在深度级别 2 和所有深度级别的结果中都考虑了该顺序。

Hierarchy Depth
1   2   3
|   |   |
IDs
1
    4
        5
        6
    2
        8
        7
        3
    9

正在寻找对我的查询进行编辑以实现上述结果。

【问题讨论】:

  • 格式有点乱我猜,你能解决它吗

标签: mysql sql common-table-expression


【解决方案1】:

我认为您可以根据排序优先级构建排序路径。不幸的是,这些似乎在不同的行上重复,所以我还要包括原始 id:

WITH RECURSIVE cte AS (
      SELECT ID, parentID, title, 0 AS depth, CAST(ID AS CHAR(200)) AS path,
             CONCAT(sort, '-', id) as sort_path
      FROM categories
      WHERE ID = 2
      UNION ALL
      SELECT c.ID, c.parentID, c.title, cte.depth + 1, CONCAT(cte.path, ',', c.ID) ,
             CONCAT(cte.sort_path, c.sort, '-', c.id, ',') as sort_path
      FROM categories c JOIN
           cte
           ON cte.parentID = c.ID
      WHERE FIND_IN_SET(c.ID, cte.path) = 0
    )
SELECT *
FROM cte
ORDER BY sort_path;

Here 是一个 dbfiddle。使用您的示例数据,这只会深入一层,因此它实际上并不能显示这是否有效。此外,这假设 id 和排序优先级不超过一个字符 - 顺便说一下,您的查询也是如此。

【讨论】:

  • 谢谢。我试图抓住你的逻辑。 "WHERE ID = 1" 以匹配原始帖子的表格。
  • 伙计,我认为您的逻辑确实有效。它适用于超过 1 个字符 ID。我还在更复杂的查询中对其进行了测试。这是糟糕的一天。 6 小时试图找到解决方案,直到你来。 !如果它真的有效,我想我欠你很多。需要再做一些测试。 !
  • 在玩了几个星期的查询之后,我刚刚意识到顺序是 1、10、11、2、3、4、5、6... 等等。 sort_path这里有问题。一个非常痛苦的解决方法是在排序号中添加前导零,这意味着 sort_path 变量将随着深度的增加而膨胀。
  • 如果您使用 MySQL 8.2 或更高版本(实际上是最新添加),我建议使用 LIMIT 子句。因为如果将 cte 限制为 99 行,这意味着生成的前导零不会超过 2 !!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-23
  • 1970-01-01
  • 2014-10-18
  • 1970-01-01
  • 2023-03-24
  • 2019-06-20
  • 2013-11-07
相关资源
最近更新 更多