用于查找匹配项的递归 SQL 查询
Recursive SQL query for finding matches
我有 5 个 SQL 表,其中包含以下列:
tbl_department:
department_id, parent_id
tbl_employee
employee_id, department_id
tbl_department_manager
department_id, employee_manager_id
tbl_request_regular_employee
request_id, employee_id
tbl_request_special_employee
request_id, employee_id
作为输入数据,我有 employee_id
和 request_id
。
我需要弄清楚员工是否有权访问该请求(无论他是否是经理)
我们不能在这里使用 ORM,因为应用程序的响应能力是我们的首要任务,脚本可能会被调用很多。
这是我要实现的逻辑:
- 首先我们根据
employee_id
查询到tbl_department_manager
,判断当前员工是否是经理(也有可能是少数部门的经理)。如果是这样,我们得到一个 department_id
的列表(如果没有找到,只是 return false)
- 如果我们在
tbl_department_manager
中至少有一个 id,我们将根据 request_id
查询 tbl_request_regular_employee
AND tbl_request_special_employee
并从两个表中获取 employee_id
(他们是一样的)
- 根据上面收集的
employee_id
,我们查询 tbl_employee
以获得员工所属的 department_id
的唯一列表。
- 最后得到第 3 页中唯一
department_id
的列表,我们可以将其与第 1 页中得到的列表进行比较。
- 然而,要注意的是,在
tbl_department
中可能有一些部门继承自我们从 p.1 获得的一个(多个)部门(因此我们可能需要根据 parent_id
直到我们找到至少一个匹配 p.1 中的一个元素)。如果 p.1 中的一个元素与 p.3 中的一个元素之间至少有一个匹配 return true。所以需要递归寻找。
有人可以提供如何在 MSSQL 中实现它的线索吗?任何帮助将不胜感激。
declare @employee_id int, @request_id int;
with reqEmployees as (
select regular_employee_id as employee_id
from tbl_request_regular_employee
where request_id = @request_id
union all --concatenate the two tables
select special_employee_id
from tbl_request_special_employee
where request_id = @request_id
),
cte as (
select e.department_id, null as parent_id
from reqEmployees r
join tbl_employee e on e.employee_id = r.employee_id -- get these employees' departments
union all
select d.department_id, d.parent_id
from cte -- recurse the cte
join tbl_department d on d.department_id = cte.parent_id -- and get parent departments
)
-- we only want to know if there is any manager row, so exists is enough
select case when exists (select 1
from cte --join on managers
join tbl_department_manager dm on dm.department_id = cte.department_id
where dm.employee_manager_id = @employee_id)
then 1 else 0 end;
我有 5 个 SQL 表,其中包含以下列:
tbl_department:
department_id, parent_id
tbl_employee
employee_id, department_id
tbl_department_manager
department_id, employee_manager_id
tbl_request_regular_employee
request_id, employee_id
tbl_request_special_employee
request_id, employee_id
作为输入数据,我有 employee_id
和 request_id
。
我需要弄清楚员工是否有权访问该请求(无论他是否是经理)
我们不能在这里使用 ORM,因为应用程序的响应能力是我们的首要任务,脚本可能会被调用很多。
这是我要实现的逻辑:
- 首先我们根据
employee_id
查询到tbl_department_manager
,判断当前员工是否是经理(也有可能是少数部门的经理)。如果是这样,我们得到一个department_id
的列表(如果没有找到,只是 return false) - 如果我们在
tbl_department_manager
中至少有一个 id,我们将根据request_id
查询tbl_request_regular_employee
ANDtbl_request_special_employee
并从两个表中获取employee_id
(他们是一样的) - 根据上面收集的
employee_id
,我们查询tbl_employee
以获得员工所属的department_id
的唯一列表。 - 最后得到第 3 页中唯一
department_id
的列表,我们可以将其与第 1 页中得到的列表进行比较。 - 然而,要注意的是,在
tbl_department
中可能有一些部门继承自我们从 p.1 获得的一个(多个)部门(因此我们可能需要根据parent_id
直到我们找到至少一个匹配 p.1 中的一个元素)。如果 p.1 中的一个元素与 p.3 中的一个元素之间至少有一个匹配 return true。所以需要递归寻找。
有人可以提供如何在 MSSQL 中实现它的线索吗?任何帮助将不胜感激。
declare @employee_id int, @request_id int;
with reqEmployees as (
select regular_employee_id as employee_id
from tbl_request_regular_employee
where request_id = @request_id
union all --concatenate the two tables
select special_employee_id
from tbl_request_special_employee
where request_id = @request_id
),
cte as (
select e.department_id, null as parent_id
from reqEmployees r
join tbl_employee e on e.employee_id = r.employee_id -- get these employees' departments
union all
select d.department_id, d.parent_id
from cte -- recurse the cte
join tbl_department d on d.department_id = cte.parent_id -- and get parent departments
)
-- we only want to know if there is any manager row, so exists is enough
select case when exists (select 1
from cte --join on managers
join tbl_department_manager dm on dm.department_id = cte.department_id
where dm.employee_manager_id = @employee_id)
then 1 else 0 end;