如何使用SQL闭包表模式(没有子查询!)获取所有兄弟表


How to fetch all siblings using SQL closure tables pattern (without subquery!)

我试图实现一个简单的菜单模型的闭包表模式,但我遇到了一些困难,构建查询,以找到当前节点的所有兄弟姐妹没有子查询(例如。加入)。

有一个与我的问题非常相似的老问题,但似乎没有答案(或者至少我不明白)。

以以下简化场景为例(不包括零深度记录):

menu:
+--+--------------+
| id | title      |
+--+--------------+
| 1  | Link 1     |  
| 2  | Link 1.1   | 
| 3  | Link 1.2   | 
| 4  | Link 1.3   | 
| 5  | Link 1.3.1 | 
| 6  | Link 1.3.2 |
+----+------------+
menu_closure:
+----------+------------+-------+
| ancestor | descendant | depth |
+----------+------------+-------+
| 1        | 2          | 1     |
| 1        | 3          | 1     |
| 1        | 4          | 1     |
| 1        | 5          | 2     |
| 1        | 6          | 2     |
| 4        | 5          | 1     |
| 4        | 6          | 1     |
+----------+------------+-------+

我想获得Link 1.1 (id=2) -> Link 1.2 (id=3)和Link 1.3 (id=4)的所有兄弟姐妹。

注意:我只知道目标menu记录的id。

目前,我做了以下操作:

SELECT m.*
FROM menu AS m
LEFT JOIN menu_closure AS mc ON mc.descendant=m.id
WHERE m.id != 2
    AND mc.depth = 1
    AND mc.ancestor = (SELECT ancestor FROM menu_closure WHERE descendant=3 AND depth=1)

我正在考虑的另一个选项是首先获得Link 1.1的父级,然后通过排除Link 1.1的id来获取其子级,但我正在寻找只有1个查询的解决方案。

首先检查ancestor

select *
from menu_closure a
where a.descendant = 2

接起兄弟姐妹

select *
from menu_closure a
join menu_closure s on s.ancestor = a.ancestor
where a.descendant = 2

在与"Link 1.1"相同的深度

select *
from menu_closure a
join menu_closure s on s.ancestor = a.ancestor
where a.descendant = 2
    and s.depth = a.depth

添加菜单标题

select *
from menu_closure a
join menu_closure s on s.ancestor = a.ancestor
join menu m on m.id = s.descendant
where a.descendant = 2
    and s.depth = a.depth

并排除所有不需要的

select m.*
from menu_closure a
join menu_closure s on s.ancestor = a.ancestor
join menu m on m.id = s.descendant
where a.descendant = 2
    and s.depth = a.depth
    and m.id <> 2
最终sqlfiddle