简体   繁体   English

嵌套集 SQL 查询以检索每个节点的第一个祖先

[英]Nested Set SQL Query to retrieve the first ancestor of each node

i have a Nested Set Tree and i am searching for an SQL query to retrieve the first ancestor of each node.我有一个嵌套集树,我正在搜索一个 SQL 查询来检索每个节点的第一个祖先。

I will always get the root node or a list of all ancestors.我总是会得到根节点或所有祖先的列表。 See: Nested Set Query to retrieve all ancestors of each node请参阅: 嵌套集查询以检索每个节点的所有祖先

Sample:样本:

The tree:那个树:

ROOT
 - A
   - B 
   - C
     - D
 - E
   - F
     - G
     - H
       - I
 - J
   - K

The needed Output:所需的输出:

|    NODE |  ACESTOR |
|---------|----------|
|       A |        A |
|       B |        A |
|       C |        A |
|       D |        A |
|       E |        E |
|       F |        E |
|       G |        E |
|       H |        E |
|       I |        E |
|       J |        J |
|       K |        J |

UPDATE : Some sample Data:更新:一些示例数据:

CREATE TABLE `nstree` (
  `sid` int,
  `left` int,
  `right` int,
  `level` int,
  `name` varchar(255)
);


INSERT INTO `nstree` (`sid`, `left`, `right`, `level`, `name`) VALUES
(1, 1, 24, 0, 'Root'),
(2, 2, 9, 1, 'A'),
(3, 3, 4, 2, 'B'),
(4, 5, 8, 2, 'C'),
(5, 6, 7, 3, 'D'),
(6, 10, 19, 1, 'E'),
(7, 11, 18, 2, 'F'),
(8, 12, 13, 3, 'G'),
(9, 14, 17, 3, 'H'),
(10, 15, 16, 4, 'I'),
(11, 20, 23, 1, 'J'),
(12, 21, 22, 2, 'K');

Will create this Table:将创建此表:

|  sid| left|right|level| name|
|-----|-----|-----|-----|-----|
|    1|    1|   24|    0| Root|
|    2|    2|    9|    1|    A|
|    3|    3|    4|    2|    B|
|    4|    5|    8|    2|    C|
|    5|    6|    7|    3|    D|
|    6|   10|   19|    1|    E|
|    7|   11|   18|    2|    F|
|    8|   12|   13|    3|    G|
|    9|   14|   17|    3|    H|
|   10|   15|   16|    4|    I|
|   11|   20|   23|    1|    J|
|   12|   21|   22|    2|    K|

The SQL query for all ancestors:所有祖先的 SQL 查询:

SELECT n.sid, n.name, GROUP_CONCAT(p.sid ORDER BY p.left) ancestors 
FROM nstree n
LEFT JOIN nstree p ON p.left < n.left AND p.right > n.right
GROUP BY n.sid; 

will produce this result:会产生这样的结果:

|  sid| name|ancestors  
|-----|-----|--------|
|    1| Root|    NULL|
|    2|    A|       1|
|    3|    B|     1,2|
|    4|    C|     1,2|
|    5|    D|   1,2,4|
|    6|    E|       1|
|    7|    F|     1,6|
|    8|    G|   1,6,7|
|    9|    H|   1,6,7|
|   10|    I| 1,6,7,9|
|   11|    J|       1|
|   12|    K|    1,11|

but i need only the first node after root但我只需要 root 之后的第一个节点

|  sid| name|ancestor| 
|-----|-----|--------|
|    1| Root|    NULL|
|    2|    A|       2|
|    3|    B|       2|
|    4|    C|       2|
|    5|    D|       2|
|    6|    E|       6|
|    7|    F|       6|
|    8|    G|       6|
|    9|    H|       6|
|   10|    I|       6|
|   11|    J|      11|
|   12|    K|      11|

As I understand your question, you want to display the level 1 ancestor only.据我了解您的问题,您只想显示 1 级祖先。 Starting from your existing query, you could just use conditional aggregation:从您现有的查询开始,您可以只使用条件聚合:

MAX(CASE WHEN p.level = 1 THEN p.sid END) as l1_ancestor

This is a bit closer to what you ask for, and would produce the result that you want:这更接近您的要求,并且会产生您想要的结果:

CASE WHEN n.level = 1 THEN n.sid ELSE MAX(CASE WHEN p.level = 1 THEN p.sid END) END res l1_ancestor

Demo on DB Fiddle : DB Fiddle 上的演示

sid | name | ancestors | l1_ancestor
--: | :--- | :-------- | ----------:
  1 | Root | null      |        null
  2 | A    | 1         |           2
  3 | B    | 1,2       |           2
  4 | C    | 1,2       |           2
  5 | D    | 1,2,4     |           2
  6 | E    | 1         |           6
  7 | F    | 1,6       |           6
  8 | G    | 1,6,7     |           6
  9 | H    | 1,6,7     |           6
 10 | I    | 1,6,7,9   |           6
 11 | J    | 1         |          11
 12 | K    | 1,11      |          11

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM