SQL 在一行中查询到 select 父子名称

SQL query to select parent and child names in one row

我在 hsqldb 中有 table 和这样的值

如何编写显示如下的查询

给你:

with recursive
n (root_id, id, title, parent) as (
  select id as root_id, id, name, parent from t
 union
  select n.root_id, t.id, t.name || '/' || n.title, t.parent
  from n
  join t on t.id = n.parent
)
select title as name from n where parent is null order by root_id

结果:

NAME      
----------
A         
A/A1      
B         
B/B1      
C         
C/C1      
A/A1/A2   
A/A1/A3   
A/A1/A3/A4
B/B1/B3   

作为参考,这是我用来测试的数据脚本:

create table t (id int, name varchar(10), parent int);

insert into t (id, name, parent) values
  (0, 'A', null),
  (1, 'A1', 0),
  (2, 'B', null),
  (3, 'B1', 2),
  (4, 'C', null),
  (5, 'C1', 4),
  (6, 'A2', 1),
  (7, 'A3', 1),
  (8, 'A4', 7),
  (9, 'B3', 3);

您可以使用递归查询:

with recursive cte (id, name, parent, path, lvl) as
    select id, name, parent, name, 0 from mytable
    union all
    select c.id, c.name, t.parent, concat(t.name, '/', c.path), c.lvl + 1
    from cte c
    inner join mytable t on t.id = c.parent_id
)
select *
from cte c
where lvl = (select max(c1.lvl) from cte c1 where c1.id = c.id)

查询选择整个table,然后爬升每一行的层次树。这种方法的好处是它可以正确处理“损坏的”树(例如 child 和无效的 parent)。

基于已接受答案的更简单的备选查询。我们只从根(父项为空的行)开始,每次执行并集时,只添加几行。如答案所示,这种查询不会 select 具有无效父 ID 的子行:

with recursive n (root_id, id, title, parent) as (
  select id as root_id, id, name, parent from t where parent is null
 union
  select n.root_id, t.id, n.title || '/' || t.name, t.parent
  from t
  join n on n.id = t.parent
)
select * from n

对于这种table,必须添加设计中隐含的引用约束。这将在 table 变大时加快查询速度,并且还将避免破坏父 ID。

alter table t add constraint pk primary key(id)
alter table t add constraint fk foreign key (parent) references t(id)