代码之家  ›  专栏  ›  技术社区  ›  Neil Barnwell

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

  •  3
  • Neil Barnwell  · 技术社区  · 14 年前

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

    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 但会满足于他的经理 工作地点 如果他没有。此时,您有两个选项:

    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:如果员工没有 工作地点 集合。

    你喜欢哪一种?为什么?

    6 回复  |  直到 14 年前
        1
  •  5
  •   Mike Killey    14 年前

    还有另一个选项-使用coalesce在T-SQL查询中指定规则还是使用空的coalescing运算符??在代码中(也适用于LinqToSQL)。

    这两种方法都只需要一次调用数据库,所以选项1的值是+1。

        2
  •  2
  •   Simon Hughes    14 年前

    我肯定会选择选项1。

    有一个同时获取和允许的查询 业务规则决定了 使用。

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

        3
  •  1
  •   Stuart Davies    14 年前

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

        4
  •  1
  •   JonPayne    14 年前

    我知道您的模式是人为的,但正如Mike建议的那样,isNull或Coalesce语句不起作用,因为WorkingLocationID不能为空,因此员工必须有一个位置。但是,如果有一个默认位置指示员工没有位置,例如使用值0,那么使用case语句将起作用。请注意,对于所需的每个工作位置字段,都需要一个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
    
        5
  •  0
  •   Beth    14 年前

    尝试两者,看看哪一个在您的环境中有更好的性能,如果发生变化,保留稍后切换方法的选项。

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

        6
  •  -1
  •   JBrooks    14 年前

    编辑:如果必须是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)