我有这个查询
WITH RECURSIVE territory_data(id,manager_id, name, geography) AS (
SELECT r.id, r.manager_id, r.name, ST_Union(bd.data)
FROM hierarchy h
JOIN reps r ON r.hierarchy_id = h.id
JOIN rep_sales_area sa ON r.id = sa.rep_id
JOIN boundary_data bd ON sa.boundary_id = bd.id
WHERE h.id = 1
GROUP BY r.id
UNION ALL
SELECT r.id, r.manager_id, r.name, ST_Union(t.geography) as geography
FROM territory_data t, reps r
WHERE t.manager_id = r.id
GROUP BY r.id
)
select * from territory_data;
基本上我要做的是销售代表控制不同的地区,他们有一个管理员控制他们下属的所有地区。所以基本上走到了链的顶端,执行官将控制整个地图。销售代表只能有1个经理,但经理可以有很多下属。我确信这可以在查询中进行,而不需要在代码中循环,但我是postgres的新手(来自mysql)所以仍然试图找出所有这些更高级的CTE函数..窗口函数等。
非常感谢任何指示,谢谢。
更新
说我有这些表和数据
create table reps (id int NOT NULL primary key, hierarchy_id int NOT NULL, name varchar(64) NOT NULL, manager_id int );
INSERT INTO reps (id, hierarchy_id, name, manager_id) VALUES
(1,1, 'John Doe', 6),
(2,1, 'Jane Doe', 7),
(3, 1, 'Mark Doe', 8),
(4,1, 'Jake Doe',8),
(5, 1, 'Henry Doe', 6),
(6, 2, 'Derek Smith', 10),
(7, 2, 'Sam Smith', 9),
(8, 2, 'Debby Smith', 9),
(9, 3, 'Carl Burk', null),
(10, 3, 'Adrian Burk', null);
create table hierarchy (id int not null primary key, name varchar(32) NOT NULL);
insert into hierarchy(id, name) values
(1, 'Sales Reps'),
(2, 'Managers'),
(3, 'Executives');
create table rep_sales_area(id int PRIMARY KEY NOT NULL, rep_id int NOT NULL, boundary_id INT NOT NULL);
insert into rep_sales_area(id, rep_id, boundary_id) VALUES
(1, 1, 10 ),
(2, 1, 11 ),
(3, 1, 12 ),
(4, 2, 13 ),
(5, 2, 14 ),
(6, 3, 15 ),
(7, 4, 16 ),
(8, 4, 17 ),
(9, 4, 18 ),
(10, 5, 19);
这是我想要的输出。注意 - 如果更容易不包含它,第一层无关紧要(id 1-5)
id | Name | Manager | boundaries
1 | John Doe | Derek Smith | 10, 11, 12
2 | Jane Doe | Sam Smith | 13, 14
3 | Mark Doe | Debby Smith | 15
4 | Jake Doe | Debby Smith | 16, 17, 18
5 | Henry Doe | Derek Smith | 19
6 | Derek Smith | Adrian Buck | 10, 11, 12, 19
7 | Sam Smith | Carl Buck | 13, 14
8 | Debby Smith | Carl Buck | 15, 16, 17, 18
9 | Carl Buck | | 13, 14, 15, 16, 17, 18
10 | Adrian Buck | | 10, 11, 12, 19
显然我想要实际的地理数据,但我认为我现在只用id来简化它。
答案 0 :(得分:1)
编辑:此版本解决了您对不支持任何层次结构的第一个版本的担忧。它使用两个递归查询,其中第二个以第一个查询为基础。我从未使用过两级递归的查询,并且非常高兴它的工作原理(至少在DB2和Postgres上)。
第二次编辑:我终于能够进入SQLFIDDLE.COM,而不是太忙,并为Postgres 9.3.1而不是之前的DB2版本重构了这个。改变是相当轻微的,以使其快乐。 SQLFIDDLE link
鉴于这是相当复杂的,并且使用一小组数据进行了最低限度的测试,我建议在将其投入生产之前将更多数据集投入其中。
with recursive
associations as (
select rep_id as owner_id, boundary_id, id as rep_sales_area_id
from rep_sales_area
union all
select s.manager_id as owner_id, a.boundary_id, a.rep_sales_area_id
from associations a
inner join reps s
on s.id = a.owner_id
where s.manager_id is not null
) ,
territories as (
select r.id as owner_id
,'' as boundary_id_list
,0 as rep_sales_area_id
,1 as row_num
from reps r
union all
select t.owner_id
,trim( t.boundary_id_list ) || case when t.boundary_id_list = '' then '' else ', ' end || n.boundary_id
,n.rep_sales_area_id
,t.row_num + 1
from territories t
cross join lateral (
select a.boundary_id, a.rep_sales_area_id
from associations a
where a.rep_sales_area_id > t.rep_sales_area_id
and a.owner_id = t.owner_id
order by a.rep_sales_area_id
limit 1
) as n
)
select id, name, manager, boundaries
from (
select owner_id as id, r.name, m.name as manager, boundary_id_list as boundaries
,row_number() over( partition by owner_id
order by row_num desc ) as ordered_row_num
from territories t
left join reps r
on r.id = t.owner_id
left join reps m
on m.id = r.manager_id
) as t
where ordered_row_num = 1
order by id