"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_id
和 request_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;
最后,我认为在上面的查询中实现了逻辑:
- 首先我们需要确定
employee_id
是否是经理。如果他是 - 找到在哪个部门。所以我们根据manager_employee_id(=employee_id from input data)
查询到tbl_department_manager
得到对应的department_id
的列表,存入一个变量中。如果查询 returned 0 departments - terminate and return false
- 基于
request_id
,我们从 tbl_request_listEmpB
和 tbl_request_listEmpD
收集员工 ID。后来我们将它们称为 employee_id
from reqEmployees
- 根据从 p.2 检索到的 ID 查询
tbl_employee
以获得 parent_id
(员工所属的唯一部门列表)
- 如果 p.1 中的至少一个部门与 p.3 中的一个部门匹配 return true
- 如果不是,则需要查询
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_ou
和 tbl_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(已更新)测试我的脚本。
我有 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_id
和 request_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;
最后,我认为在上面的查询中实现了逻辑:
- 首先我们需要确定
employee_id
是否是经理。如果他是 - 找到在哪个部门。所以我们根据manager_employee_id(=employee_id from input data)
查询到tbl_department_manager
得到对应的department_id
的列表,存入一个变量中。如果查询 returned 0 departments - terminate and return false - 基于
request_id
,我们从tbl_request_listEmpB
和tbl_request_listEmpD
收集员工 ID。后来我们将它们称为employee_id
fromreqEmployees
- 根据从 p.2 检索到的 ID 查询
tbl_employee
以获得parent_id
(员工所属的唯一部门列表) - 如果 p.1 中的至少一个部门与 p.3 中的一个部门匹配 return true
- 如果不是,则需要查询
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_ou
和 tbl_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(已更新)测试我的脚本。