簡體   English   中英

MySql 遞歸 - 從給定 id 獲取所有孩子和父母

[英]MySql Recursive - get all children and parents from a given id

MySQL 版本 8.0 架構 SQL

CREATE TABLE IF NOT EXISTS `department` (
  `id` INT NOT NULL,
  `name` VARCHAR(45) NOT NULL,
  `father` INT NULL,
  PRIMARY KEY (`id`),
  INDEX `fk_department_department_idx` (`father` ASC) VISIBLE,
  CONSTRAINT `fk_department_department`
    FOREIGN KEY (`father`)
    REFERENCES `department` (`id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

insert into department (id,name,father)
values
(1, 'dp1',null),
(2, 'dp2',null),
(3, 'dp3',1),
(4, 'dp4',1),
(5, 'dp5',2),
(6, 'dp6',4),
(7, 'dp7',6),
(8, 'dp8',6),
(9, 'dp9',6);

SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
SET SESSION sql_mode = '';

我的查詢:

WITH RECURSIVE cte_department AS (
      SELECT 
          d1.id, 
          d1.name, 
          d1.father
      FROM
          department d1
      WHERE
          d1.id=6
    UNION ALL
      SELECT 
          d2.id, 
          d2.name, 
          d2.father
      FROM
          department d2
      INNER JOIN cte_department cte ON cte.id = d2.father
)
SELECT * FROM cte_department;

結果:

id  name    father
6   dp6      4
7   dp7      6
8   dp8      6
9   dp9      6

我需要的:

id  name    father
1   dp1      null
4   dp4      1
6   dp6      4
7   dp7      6
8   dp8      6
9   dp9      6

問題是:我可以獲取所有孩子,但我需要將給定 ID 中的所有父母添加到此查詢中,在本例中為 ID 6。我堅持這一點。 如果有人可以幫助我,請跟隨小提琴。

https://www.db-fiddle.com/f/g8YkE3hqsvaw8G9vdHPyyF/0

遞歸部分可以有多個查詢塊。

WITH RECURSIVE cte_department AS (
      SELECT 
          d1.id,
          d1.name,
          d1.father,
          'Begin' state
      FROM
          department d1
      WHERE
          d1.id=6
    UNION ALL
      SELECT 
          d2.id,
          d2.name,
          d2.father,
          'Up'
      FROM
          department d2
      INNER JOIN
          cte_department cte
      ON
          cte.father = d2.id
      WHERE
          cte.state in ('Begin', 'Up')
    UNION ALL
      SELECT 
          d2.id,
          d2.name,
          d2.father,
          'Down'
      FROM
          department d2
      INNER JOIN
          cte_department cte
      ON
          cte.id = d2.father
      WHERE
          cte.state in ('Begin', 'Down')
)
SELECT
    id, name, father
FROM
    cte_department
ORDER BY
    father, id, name;

db<>fiddle上試試。

我會使用兩個單獨的遞歸查詢:一個帶孩子,另一個帶父母,然后union結果。 您可以跟蹤每個節點的級別以正確排序結果集中的記錄:

with recursive 
    children as (
        select 1 as lvl, d.* from department d where id = 6
        union all
        select c.lvl, d.* from department d inner join children c on c.id = d.father
    ),
    parents as (
        select 1 as lvl, d.* from department d where id = 6
        union all
        select p.lvl - 1, d.* from department d inner join parents p on d.id = p.father
    )
select * from parents
union   -- on purpose, to remove the duplicate on id 6
select * from children
order by lvl;

這比在同一個查詢中有多個union all成員更安全。 MySQL 不保證遞歸中成員的評估順序,因此使用此技術可能會導致意外行為。

DB Fiddle 上的演示


與您的問題無關,但是:您的代碼中可以看到以下內容:

SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
SET SESSION sql_mode = '';

只是不要。 ONLY_FULL_GROUP_BY的存在是有充分理由的,即 MySQL 在聚合查詢方面的行為與 SQL 標准一致。 禁用此 SQL 模式絕不是一個好主意。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM