我有好奇心。请在这里建议我最好的做法。
我有一个包含empname和mgr_name列的表测试,因为名称建议empname包含empname,mgr_name包含特定员工的经理名称。我的要求是找到那些至少向一位经理和管理人员报告的员工。
我写了一个查询,并返回正确的记录。
create table test(empname varchar(10),mgr_name varchar(10))
insert into test
values('a','b'),('b',null),('c',null),('d','f'),('f',null),('g',null),('h',null)
查询:
select a.empname
from test a , test b
where a.mgr_name =b.empname
union
select b.empname
from test a , test b
where a.mgr_name =b.empname
我尝试优化此查询并使用CTE而不是多次使用自连接中的表,如
;with cte as (
select *
from test
)
select a.empname
from cte a , cte b
where a.mgr_name =b.empname
union
select b.empname
from cte a , cte b
where a.mgr_name =b.empname
但我发现执行计划中没有任何改善。
在这种情况下,我需要您的帮助来决定优化查询,请在此情况下建议是否优化任何其他方法。
答案 0 :(得分:0)
对指定指标(无)的优化会导致以下内容提供所有人员的列表,以及他们是(1)由某人管理还是(b)管理某人:
declare @Employees as Table ( EmployeeName VarChar(10), ManagerName VarChar(10) );
insert into @Employees ( EmployeeName, ManagerName ) values
( 'a', 'b' ), ( 'b', null ), ( 'c', null ), ( 'd', 'f' ), ( 'f', null ), ( 'g', null ), ( 'h', null );
select distinct( Name ),
case when exists
( select 42 from @Employees where EmployeeName = Name and ManagerName is not NULL ) then 1 else 0 end as IsManaged,
case when exists
( select 42 from @Employees where ManagerName = Name ) then 1 else 0 end as IsManager
from (
select EmployeeName as Name
from @Employees
union all
select ManagerName
from @Employees
where ManagerName is not NULL ) as PH;
-- Alternatively:
select Name, Max( IsManaged ) as IsManaged, Max( IsManager ) as IsManager
from (
select EmployeeName as Name, case when ManagerName is NULL then 0 else 1 end as IsManaged, 0 as IsManager
from @Employees
union all
select ManagerName, 0, 1
from @Employees
where ManagerName is not NULL ) as PH
group by Name;
支持自我管理。
答案 1 :(得分:0)
实际上,您的CTE没有做任何事情。您只是准确地复制一个表,因此与使用cte或test没有区别。你可能想做的事情如下:
; with cte as (
select * -- This won't work because duplicate naming, but you can change that
from test a, test b -- my soul weeps at this terrible syntax
)
无论如何,您不需要这样做。这是您想要的查询
select empname
from test
where mgr_name is not null
or empname in (
select mgr_name
from test
)
答案 2 :(得分:-1)
无需查询表格4次...只需检查mgr_name
的值是否为 NULL
:
SELECT empname
FROM test
WHERE mgr_name IS NOT NULL
UNION
SELECT mgr_name
FROM test
WHERE mgr_name IS NOT NULL;
您仍然需要进行2次扫描,但除了隐式JOIN
以及2次扫描之外(在查询中,表格在每次扫描时扫描两次) UNION
)。