gpt4 book ai didi

php - MySQL 不允许在递归公用表表达式中使用 LIMIT

转载 作者:行者123 更新时间:2023-12-05 07:06:34 25 4
gpt4 key购买 nike

我的目标是使用最新的 MySQL 的 WITH RECURSIVE 方法构造一棵树。

我的表名为 categories,它有 2 行。 IDparentID 行

我的类别表:

 . ID . | ParentID   
--------|----------
. 1 . | null
. 2 . | 1
. 3 . | 1
. 4 . | 1
. 6 . | 1
. 7 . | 1
. 8 . | 1
. 9 . | 1
. 10 . | 1
. 11 . | 13
. 12 . | 14
. 13 . | 12
.... . | ...

从 2 到 9 的 ID 具有相同的父级,该父级是 ID = 1 的父级。这就是我试图通过在我的递归公用表表达式的第二个 SELECT 查询中提供“LIMIT 5”来限制的内容。

上表在树中的光学表示如下所示:我的问题是限制同一​​级别的 child 数量(在下图中标记为项目 Y)。

+ Item X .............. (level 1)       
+ Item Y .............. (level 2)
+ Item Y .............. (level 2)
+ Item Y .............. (level 2)
+ .... LIMIT to 5 Items
+ Item X
+ Item X
+ Item X
+ Item X
+ Item X
+ Item X

这是我的 mySQL Recursive Common Table Expression 使用 LIMIT 子句查询导致问题:

WITH RECURSIVE cte AS
(
SELECT ID, 0 AS depth, CAST(ID AS CHAR(200)) AS path
FROM categories WHERE parentID = 1
UNION ALL
SELECT c.ID, cte.depth+1, CONCAT(cte.path, ',', c.ID)
FROM categories c
JOIN cte ON cte.ID = c.parentID
WHERE FIND_IN_SET(c.ID, cte.path)=0 AND depth <= 10
LIMIT 5
)

SELECT * FROM cte

从逻辑上讲,我希望通过在 CTE 的第二个 Select 部分中使用 LIMIT 子句来对我的问题进行排序,以限制第二个 SELECT 语句返回的行数。但它给了我一个错误:

This version of MySQL doesn't yet support 'ORDER BY / LIMIT over UNION in recursive Common Table Expression'

请注意,我使用的是 MySQL 8.0+ 版本。我知道错误很明显。但是,如果我在同一个 parent 之下有 100 万个 child 呢?它会卡住系统!

我将不胜感激。

谢谢。

最佳答案

如果我没听错,row_number() 可以做你想做的事。这个想法是在递归部分枚举 categories 行,然后过滤前 5 行:

with recursive cte as (
select id, 0 as depth, cast(id as char(200)) as path
from categories
where parentid = 1
union all
select c.id, cte.depth+1, concat(cte.path, ',', c.id)
from cte
inner join (
select c.*, row_number() over(partition by c.parentid order by c.id) rn
from categories c
) c on cte.id = c.parentid
where find_in_set(c.id, cte.path) = 0 and depth <= 10 and c.rn <= 5
)
select * from cte

您可以通过预过滤数据集来稍微优化一下:

with recursive 
cats as (
select *
from (
select c.*, row_number() over(partition by parentid order by id) rn
from categories c
) t
where rn <= 5
),
cte as (
select id, 0 as depth, cast(id as char(200)) as path
from cats
where parentid = 1
union all
select c.id, cte.depth+1, concat(cte.path, ',', c.id)
from cte
inner join cats c on cte.id = c.parentid
where find_in_set(c.id, cte.path) = 0 and depth <= 10 and c.rn <= 5
)
select * from cte

关于php - MySQL 不允许在递归公用表表达式中使用 LIMIT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62429036/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com