进行两用查询,还是两个单独的查询?

时间:2010-08-23 14:29:05

标签: sql performance

这是一个人为的例子,但考虑的情况是员工有工作地点,员工有经理也有工作地点:

create table WorkingLocation (
    ID int not null primary key identity(1,1), 
    Name varchar(50)
)

create table Employee (
    ID int not null primary key identity(1,1), 
    Name varchar(50), 
    WorkingLocationID int null,
    ManagerID int null,
    constraint FK_Employee_WorkingLocation foreign key (WorkingLocationID) references WorkingLocation (ID),
    constraint FK_Employee_Manager foreign key (ManagerID) references Employee (ID)
)

现在考虑一个需要员工WorkingLocation的业务规则,但如果他没有,则会为他的经理WorkingLocation求助。此时您有两个选择:

1:有一个查询同时获取并让业务规则决定使用哪个:

select 
    e.*,
    emp_location.*,
    mgr_location.*
from Employee e
    left join WorkingLocation emp_location on e.WorkingLocationID = emp_location.ID
    left join Employee mgr on e.ManagerID = mgr.ID
    left join WorkingLocation mgr_location on mgr.WorkingLocationID = mgr_location.ID
where e.ID = @id

2:如果员工未设置WorkingLocation,则单独调用数据库以检索经理的详细信息。

您更喜欢哪个?为什么?

6 个答案:

答案 0 :(得分:5)

还有另一种选择 - 使用COALESCE在T-SQL查询中指定规则或使用null-coalescing运算符?在你的代码中(也适用于LinqToSQL)。

其中任何一个只需要一次调用数据库,因此选项1为+1。

答案 1 :(得分:2)

我最肯定会选择选项1.

  

有一个得到两者并让它的查询   业务规则决定了哪些   使用

我总是说避免多次调用数据库,除非你收回不合理数量的数据和/或查询需要很长时间。

答案 2 :(得分:1)

如果您不关心返回的位置,那么正如迈克所说,您可以考虑合并员工和经理的位置。但是,这确实会将业务逻辑转移到您可能认为的数据访问层,因此,根据您的严格程度,您可能更愿意在其他地方强制执行此类规则。在这种情况下,我可能会投票选择选项1。

答案 3 :(得分:1)

我知道你的架构是人为的,但正如迈克所建议的那样ISNULL或COALESCE声明不会起作用,因为WorkingLocationID不可为空,因此员工必须有一个位置。但是,如果存在指示员工没有位置的默认位置,例如使用值0,则使用CASE语句将起作用。请注意,您需要为每个WorkLocation字段提供CASE语句。所以查询变成了:

   SELECT e.*
        , CASE
              WHEN emp_location.WorkingLocationID = 0
              THEN mgr_location.ID
              ELSE emp_location.ID
          END AS Location
        , CASE
              WHEN emp_location.WorkingLocationID = 0
              THEN mgr_location.Name
              ELSE emp_location.Name
          END AS Name
     FROM Employee e
LEFT JOIN WorkingLocation emp_location
       ON e.WorkingLocationID = emp_location.ID
LEFT JOIN Employee mgr
       ON e.ManagerID = mgr.ID
LEFT JOIN WorkingLocation mgr_location
       ON mgr.WorkingLocationID = mgr_location.ID
    WHERE e.ID = @id

答案 4 :(得分:0)

尝试两者并查看哪些内容在您的环境中具有更好的性能,如果出现更改,请保留稍后切换方法的选项。

我认为你不必选择一种解决方案并永远坚持下去。

答案 5 :(得分:-1)

编辑:如果必须是1则选择:

select e.*, wl.*
from Employee e 
inner join WorkingLocation wl
on e.WorkingLocationID = wl.ID
union
select e.*, wl.*
from Employee e 
inner join Employee m
on m.ID = e.ManagerID 
inner join WorkingLocation wl
on m.WorkingLocationID = wl.ID
where not exists (select 1
   from WorkingLocation wl
   on wl.ID = e.WorkingLocationID)