具有层次结构和层次数可变的查询

问题描述 投票:0回答:1

我有包含客户区域的表“ Areas”:

ID, AREA_NAME, PARENT_ID

区域使用指向父级的AREA_ID的PARENT_ID分为四个层次。顶层区域的PARENT_ID为NULL。

“客户”表具有引用区域层次结构最低级别的AREA_ID:

ID, CUSTOMER_NAME, AREA_ID

我想得到这样的结果表:

CUSTOMER_NAME,AREA_LVL_1,AREA_LVL_2,AREA_LVL_3,AREA_LVL_4

这里的问题是客户区域(AREA_ID)始终不指向最低的第四级区域。有时它指向第四级AREA_ID,有时指向第三级,依此类推。

取决于区域级别,结果表应如下所示:

CUSTOMER_NAME | AREA_LVL_1 | AREA_LVL_2 | AREA_LVL_3 | AREA_LVL_4
==============+============+============+============+===========
John          | A          | A1         | A13        | A136
Maria         | B          | B2         | <null>     | <null>
Steve         | A          | A2         | A24        | <null>

我不知道如何在单个SQL查询中使用可变数量的级别进行此递归。我只需要单个SQL查询(而不是带有游标通过递归循环的过程)。

sql sql-server hierarchy
1个回答
0
投票

您需要一个递归的CTE,它返回将要加入customers的每个区域的所有级别:

with 
  cte as (
    select id, area_name, parent_id, id start, 4 level from areas
    union all
    select a.id, a.area_name, a.parent_id, c.start, c.level - 1 
    from areas a inner join cte c
    on c.parent_id = a.id
    where c.parent_id is not null
  ),
  levels as (
    select id, area_name, parent_id, start, 
      level + 1 - min(level) over (partition by start) level 
    from cte
  )
select c.customer_name,
  max(case when l.level = 1 then l.area_name end) area_lvl_1,
  max(case when l.level = 2 then l.area_name end) area_lvl_2,
  max(case when l.level = 3 then l.area_name end) area_lvl_3,
  max(case when l.level = 4 then l.area_name end) area_lvl_4
from customers c left join levels l 
on l.start = c.area_id 
group by c.id, c.customer_name

请参见demo。结果:

> customer_name | area_lvl_1 | area_lvl_2 | area_lvl_3 | area_lvl_4
> :------------ | :--------- | :--------- | :--------- | :---------
> John          | A          | A1         | A13        | A136      
> Maria         | B          | B2         | null       | null      
> Steve         | A          | A2         | A24        | null 
© www.soinside.com 2019 - 2024. All rights reserved.