SQL查询在一行中选择父名和子名

Posted

技术标签:

【中文标题】SQL查询在一行中选择父名和子名【英文标题】:SQL query to select parent and child names in one row 【发布时间】:2020-08-15 21:22:29 【问题描述】:

我在 hsqldb 中有表和这样的值

如何编写这样显示的查询

【问题讨论】:

请向我们展示您到目前为止所做的尝试 我已经尝试过 (recursive,join,....) 方法,但没有得到任何结果。我手动创建了这个结果! 【参考方案1】:

给你:

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);

【讨论】:

【参考方案2】:

您可以使用递归查询:

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)

查询选择整个表,然后爬上每一行的层次结构树。这种方法的好处是它可以正确处理“损坏”的树(例如具有无效父级的子级)。

【讨论】:

【参考方案3】:

基于接受的答案的另一种更简单的查询。我们只从根(父项为空的行)开始,每次执行联合时,只添加几行。正如答案所示,这种查询不会选择父 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

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

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

【讨论】:

以上是关于SQL查询在一行中选择父名和子名的主要内容,如果未能解决你的问题,请参考以下文章

SQL主外键和子查询

SQL关联查询 直接join 和子查询的区别

如何在 SQL 查询中选择每个组的第一行?

获取特定子记录的 SQL 查询

sql查询表中字段名和数据

sql中的SQL连接和子查询