Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySql递归-从给定id获取所有子项和父项_Mysql_Sql_Common Table Expression_Hierarchical Data_Recursive Query - Fatal编程技术网

MySql递归-从给定id获取所有子项和父项

MySql递归-从给定id获取所有子项和父项,mysql,sql,common-table-expression,hierarchical-data,recursive-query,Mysql,Sql,Common Table Expression,Hierarchical Data,Recursive Query,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_depar

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)中的所有家长添加到此查询中。 我受够了。如果有人能帮助我,请随大流


递归部分可以有多个查询块

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;

试试看。

我将使用两个独立的递归查询:一个用于带孩子,另一个用于父母,然后
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;
这比在同一查询中使用多个
联合所有
成员更安全。MySQL不保证递归中成员的求值顺序,因此使用此技术可能会导致意外行为


与您的问题无关,但是:在您的代码中可以看到以下内容:

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

别这样
只有_FULL _GROUP _BY
有一个很好的理由,那就是让MySQL在聚合查询方面与SQL标准保持一致。禁用此SQL模式从来不是一个好主意。

这是一个很好的解决方案。我在Oracle中也尝试过同样的方法,但Oracle不允许在递归部分中使用第二个
UNION ALL
,即使我使用括号也不行。我将两个“向上”和“向下”查询合并为一个向上/向下查询。MySQL允许在这里使用
UNION ALL
,以使查询非常可读,这很好。谢谢分享。@ThorstenKettner MySQL支持UNION ALL,这很好MySQL允许任意数量的递归块以及它们之间的UNION ALL/DISTINCT混合(但它不定义递归子查询处理的顺序,因此在某些情况下,输出甚至可能是不确定的)。@Akina:我甚至没有问任何问题。我不是OP:-)Thx的答案和提示,关于
ONLY\u FULL\u GROUP\u BY