我之前尝试过提问,但如果没有正确的术语,我很难提出具体的问题,我并不熟悉。所以这是一个例子
以此查询为例:
(
SELECT *
FROM comments
WHERE depth = 0
ORDER BY id DESC
LIMIT 2
)
UNION ALL
(
SELECT c.*
FROM comments c JOIN
(
SELECT id
FROM comments
WHERE depth = 0
ORDER BY id DESC
LIMIT 2
) p ON c.parent_id = p.id
LIMIT 5
)
id parent_id depth title
1 0 0 Title 1
2 0 0 Title 2
3 1 1 Title 3
4 1 1 Title 4
5 1 1 Title 5
6 1 1 Title 6
7 1 1 Title 7
我得到两个深度0行,并且在连接中我也得到了这两个返回查询的5个子元素。我想得到的是获得这两个查询中的每一个的5个子元素,总共10行(深度为1)。例如:
id parent_id depth title
1 0 0 Title 1
2 0 0 Title 2
3 1 1 Title 3
4 1 1 Title 4
5 1 1 Title 5
6 1 1 Title 6
7 1 1 Title 7
8 2 1 Title 8
9 2 1 Title 9
10 2 1 Title 10
11 2 1 Title 11
12 2 1 Title 12
是否可以使用邻接列表以及将所有内容作为union(flat)返回的要求?
编辑: 感谢Bill Karwin的回答,我现在就开始工作了。我还在想是否有更短的方式来写这个。我有6(0-5)深度级别,所以我的查询相当长(可能不是最优)。这是三个级别的样子(你可以想象完整的那个)。
-- DEPTH LEVEL 0
(
SELECT * FROM (
SELECT *, 1 as _rn, @parent:=0
FROM comments
WHERE depth = 0
ORDER BY id DESC
LIMIT 2
) as D0
)
union all
-- DEPTH LEVEL 1
(
SELECT *
FROM (
SELECT c.*, @row:=IF(@parent=c.comment_id,@row+1,1) AS _rn, @parent:=c.comment_id
FROM (SELECT @parent:=null) AS _init
STRAIGHT_JOIN comments c
INNER JOIN
(
SELECT id
FROM comments
WHERE depth = 0
ORDER BY id DESC
LIMIT 2
) p ON c.comment_id = p.id
) AS _ranked
WHERE _ranked._rn <= 5
)
union all
-- DEPTH LEVEL 2
(
SELECT *
FROM (
SELECT c.*, @row:=IF(@parent=c.comment_id,@row+1,1) AS _rn, @parent:=c.comment_id
FROM (SELECT @parent:=null) AS _init
STRAIGHT_JOIN comments c
INNER JOIN
(
(
SELECT *
FROM (
SELECT c.*, @row:=IF(@parent=c.comment_id,@row+1,1) AS _rn, @parent:=c.comment_id
FROM (SELECT @parent:=null) AS _init
STRAIGHT_JOIN comments c
INNER JOIN
(
SELECT id
FROM comments
WHERE depth = 0
ORDER BY id DESC
LIMIT 2
) p ON c.comment_id = p.id
) AS _ranked
WHERE _ranked._rn <= 2
)
) p ON c.comment_id = p.id
) AS _ranked
WHERE _ranked._rn <= 2
)
答案 0 :(得分:1)
您不能使用LIMIT执行此操作,因为在完成所有加入,分组,排序等结果集完成后应用LIMIT。
您正在使用greatest-n-per-group类型查询的变体。在MySQL中执行此操作非常棘手,因为MySQL不支持许多其他SQL数据库支持的ROW_NUMBER()窗口函数。
这是MySQL的一种解决方法,其中用户定义的变量可以取代分区的行号:
SELECT *
FROM (
SELECT c.*, @row:=IF(@parent=c.parent_id,@row+1,1) AS _rn, @parent:=c.parent_id
FROM (SELECT @parent:=null) AS _init
STRAIGHT_JOIN comments c
INNER JOIN
(
SELECT id
FROM comments
WHERE depth = 0
ORDER BY id DESC
LIMIT 2
) p ON c.parent_id = p.id
) AS _ranked
WHERE _ranked._rn <= 5