"Column "parent_id"for "cte" is specified more thance once" in SQL recursive query

"Column "parent_id" for "cte" is specified more than once" in SQL recursive query

我有 5 个 SQL table 列如下:

tbl_request_listEmpB
listEmpB_id request_id

tbl_request_listEmpD
listEmpD_id request_id

tbl_employee
id, parent_id (this one refers to id in tbl_department)

tbl_department
id, parent_id (that one referes to id of parent department)

tbl_department_manager
department_id, manager_employee_id

作为输入数据,我有 employee_idrequest_id

我需要弄清楚员工是否有权访问该请求(无论他是否是经理)

这是应该 return 如果当前用户是经理则为 1 的查询,否则为 0

 with reqEmployees as (
    select listEmpB_id as employee_id
    from tbl_request_listEmpB
    where request_id = ${request_id}
  union all --concatenate the two tables
    select listEmpD_id
    from tbl_request_listEmpD
    where  request_id = ${request_id}
),
cte as (
    select e.parent_id, null as parent_id
    from reqEmployees r
    join tbl_employee e  on e.id = r.employee_id -- get these employees' departments
    union all
    select d.id, d.parent_id
    from cte
    join tbl_department d on d.id = cte.parent_id    -- and get parent departments
)
select case when exists (select 1
    from cte  
    join tbl_department_manager dm on dm.department_id = cte.id
    where dm.manager_employee_id = ${employee_id})
  then 1 else 0 end;

最后,我认为在上面的查询中实现了逻辑:

  1. 首先我们需要确定employee_id是否是经理。如果他是 - 找到在哪个部门。所以我们根据manager_employee_id(=employee_id from input data)查询到tbl_department_manager得到对应的department_id的列表,存入一个变量中。如果查询 returned 0 departments - terminate and return false
  2. 基于 request_id,我们从 tbl_request_listEmpBtbl_request_listEmpD 收集员工 ID。后来我们将它们称为 employee_id from reqEmployees
  3. 根据从 p.2 检索到的 ID 查询 tbl_employee 以获得 parent_id(员工所属的唯一部门列表)
  4. 如果 p.1 中的至少一个部门与 p.3 中的一个部门匹配 return true
  5. 如果不是,则需要查询 tbl_department 并递归搜索 p.1 中的至少一个元素与 p.1 中的一个元素之间的匹配项。3.parent_id

这就是我的意思

考虑以下图表

这里是对应的SQL table:

tbl_department (id, parent_id)
dep0   null
dep1   dep0
dep2   dep1
dep3   dep1
dep4   dep2
dep5   dep0

因此,如果我们有一个部门列表 return 来自 ['dep1'] 的第 1 页(可能有多个元素,我们必须遍历每个元素)我们需要 return 仅当从第 3 页我们得到 dep1|dep2|dep3|dep4 - (dep1 descendants including dep1) 时才为真。如果 ['dep2'] return 如果 dep2|dep4 为真。因此,应该至少有一个来自 p.1 的至少一个元素与来自 p.5 的递归结果的匹配。我希望我能以最清楚的方式说明它

差点忘了 - 上面的查询给了我

"Column "parent_id" for "cte" is specified more than once" 

但我不认为它做了它应该做的事情,我需要重写它

如有任何帮助,我们将不胜感激

没有一些示例数据(和参数值)和该数据的预期输出(使用这些参数值),很难验证此解决方案。

我假设你的 tbl_outbl_department 实际上是相同的 table。

除了 CTE 之外,您的其余代码看起来应该可以工作。下面的 CTE 现在通过层次结构(向上和向下)“双向”移动,找到 parents 和 children。请注意,它只找到 parents 的 parents 和 children 的 children,它没有找到 parents 的 children,例如,所以没有“兄弟姐妹”,“叔叔”或任何这些记录应该被称为!

您可能需要将 CTE 种子记录中的两个字段都转换为相关数据类型。根据提供的数据,我假设部门 id(因此也是 parent_id)的数据类型是 varchar(10).

cte as (
select
    cast(e.parent_id as varchar(10)) as id,
    cast(o.parent_id as varchar(10)) as parent_id,
    0 as iteration  
from
    reqEmployees r
    join tbl_employee e  on e.id = r.employee_id
    join tbl_department o on e.parent_id = o.id 
    --extra table here compared to earlier versions to allow us
    --to traverse hierarchy in both directions

union all

select --This one finds "child" departments
    o.id,
    o.parent_id,
    cte.iteration + 1
from
    cte
    join tbl_department o on o.id = cte.parent_id
where    
    cte.iteration >=0 --prevents siblings/uncles etc

union all

select --This one finds "parent" departments
    o.id,
    o.parent_id,
    cte.iteration - 1
from
    cte
    join tbl_department o on o.parent_id = cte.id 
where    
    cte.iteration <=0 --prevents siblings/uncles etc
  
)

您可以使用此 SQL Fiddle(已更新)测试我的脚本。