检索SQL中的分层覆盖比UNION ALL更有效的方法是什么?

时间:2015-02-06 22:19:33

标签: sql-server tsql

我正在尝试构建一个在层次结构中从适当级别(从客户端到员工)设置默认值的功能,并允许将默认值设置为可能的最高级别(以最小化不必要的数据)。此功能将被频繁执行(每天数千次),并且底层配置数据将太不稳定而无法进行有意义的缓存。

我知道我可以使用以下语句来获取我需要的内容(通过第一行),但我想知道是否有更有效的语句来实现相同的目标。

这是我正在使用的数据类型的简化示例。

如果图片没有内嵌显示,则显示在这里 - !http://imgur.com/TT0E2aY

下面的代码表示带有两组不同参数的UNION ALL语句,以显示正常工作的基础行为(并且已正确编制索引)但我想确保我没有遗漏可以提高效率的内容。

DECLARE @ClientID VARCHAR(20)
DECLARE @OfficeID VARCHAR(20)
DECLARE @DepartmentID VARCHAR(20)
DECLARE @EmployeeID VARCHAR(2

这组参数将首先返回员工特定的覆盖记录(SettingID 400),因为该员工有完全限定的条目,

SELECT @ClientID = 'Acme', @OfficeID = 'Chicago', @DepartmentID = 'Finance', @EmployeeID = 'JDOE'

这组参数将首先返回Office特定的覆盖记录(SettingID 200),因为该Office有一个合格的条目(但不是部门或员工)

SELECT @ClientID = 'Acme', @OfficeID = 'Chicago', @DepartmentID = 'IT', @EmployeeID = 'JSMITH'

这是我目前正在执行的查询。 。

SELECT HierarchyOverrideID, SettingID FROM HierarchyOverride WHERE ClientID = @ClientID AND OfficeID = @OfficeID AND DepartmentID = @DepartmentID AND EmployeeID = @EmployeeID
UNION ALL 
SELECT HierarchyOverrideID, SettingID FROM HierarchyOverride WHERE ClientID = @ClientID AND OfficeID = @OfficeID AND DepartmentID = @DepartmentID  AND EmployeeID IS NULL
UNION ALL
SELECT HierarchyOverrideID, SettingID FROM HierarchyOverride WHERE ClientID = @ClientID AND OfficeID = @OfficeID AND DepartmentID IS NULL  AND EmployeeID IS NULL
UNION ALL
SELECT HierarchyOverrideID, SettingID FROM HierarchyOverride WHERE ClientID = @ClientID AND OfficeID IS NULL AND DepartmentID IS NULL  AND EmployeeID IS NULL

3 个答案:

答案 0 :(得分:0)

这可能不是您正在寻找的答案,但我认为这些数据的结构很糟糕。

据推测,您拥有ClientOfficeDepartmentEmployee表,所有这些表都相互关联。如果将SettingId放在每个表中,则可以编写如下所示的查询:

SELECT COALESCE (e.settingid,
                 d.settingid,
                 o.settingid,
                 c.setting_id) as settingid
FROM   client c
       LEFT JOIN office o
          ON c.clientid = o.clientid AND o.officeid = @officeid
       LEFT JOIN department d
          ON c.officeid = d.officeid AND d.departmentid = @departmentid
       LEFT JOIN employee e
          ON d.departmentid = e.departmentid AND e.employeeid = @employeeid
WHERE  c.clientid = @clientid

不可否认,我做了很大的假设1)关于你的数据结构是什么样的,2)你在这个阶段改变了这个结构。鉴于这些假设,我认为使用这种模式会更容易。

答案 1 :(得分:0)

下一个解决方案应该为您提供您想要的设置而无需在代码中进行进一步处理,但我无法预测执行时间的条款。

SELECT HierarchyOverrideId, SettingId
FROM ( SELECT HierarchyOverrideId, SettingId, RowNum = ROW_NUMBER() OVER(ORDER BY CASE 
                                WHEN EmployeeId is not null THEN 1
                                WHEN DepartmentId is not null THEN 2
                                WHEN OfficeId is not null THEN 3
                                ELSE 4
                              END )
    FROM dbo.HierarchyOverride
    WHERE (EmployeeId = @EmployeeID OR EmployeeId is NULL)
     AND (DepartmentId   = @DepartmentId  OR DepartmentId  is NULL)
     AND (OfficeID  = @OfficeID  OR OfficeID is NULL)
     AND ClientId = @ClientID
) as a
WHERE a.RowNum = 1

答案 2 :(得分:0)

这是否涵盖了它?

SELECT HierarchyOverrideID, SettingID 
  FROM HierarchyOverride 
 WHERE ClientID = @ClientID 
   AND (    (   OfficeID = @OfficeID                        and DepartmentID = @DepartmentID and (EmployeeID = @EmployeeID or EmployeeID IS NULL ) )
         OR ( ( OfficeID = @OfficeID OR  OfficeID is null ) and DepartmentID is null         and  EmployeeID IS NULL ) 
       )