SQL Server 2012 Lazy Join

时间:2013-12-06 22:17:11

标签: sql sql-server-2012 left-join database

我正在开发一个应用程序,允许用户动态选择他们看到的内容。那些属于的列和表的列表是巨大的。我正在构建一个动态查询,但如果我没有,我不想存储所有的连接逻辑。 一个例子是我有一个查询对10个表有LEFT JOINS但我只选择并过滤一个表。 SQL Server 2012 Smart是否足以不加入其他不需要的表?

我知道Oracle的DBMS就像这样,但是我的公司使用的是SQL Server 2012,所以我坚持认为。

示例查询不需要执行最后4个LEFT JOINS的地方:

SELECT [IncidentIncidentNumberModValue].[IncidentNumber]
    ,IncidentNumberModifierNotValue.[Value] AS IncidentNumberNotValue
    ,[Incident].[IncidentDate]
    ,[Incident].[ResponseNumber]
    ,[Incident].[PatientCareReportNumber]
    ,[IncidentType].[Value] AS IncidentType
    ,[SceneStreetAddressModValue].[StreetAddress2] AS IncidentAddress
    ,IncidentStreetAddressNotValue.[Value] AS IncidentAddressNotValue
    ,COUNT(*) OVER() AS TotalRecordCount
FROM [EmsEvent].[Incident]
    LEFT JOIN [Resource].[IncidentType] ON [EmsEvent].[Incident].[IncidentType] = [Resource].[IncidentType].[IncidentTypeID]
    LEFT JOIN [EmsEvent].[IncidentIncidentNumberModValue] ON [EmsEvent].[Incident].[IncidentID] = [EmsEvent].[IncidentIncidentNumberModValue].[IncidentID]
    LEFT JOIN [GlobalResource].[IncidentNumberModifier] ON [EmsEvent].[IncidentIncidentNumberModValue].[NotValue] = [GlobalResource].[IncidentNumberModifier].[DataElementID]
    LEFT JOIN [GlobalResource].[NotValue] IncidentNumberModifierNotValue ON [GlobalResource].[IncidentNumberModifier].[NotValueID] = IncidentNumberModifierNotValue.[NotValueID]
    LEFT JOIN [EmsEvent].[Scene] ON [EmsEvent].[Scene].[IncidentID] = [EmsEvent].[Incident].[IncidentID]
    LEFT JOIN [EmsEvent].[SceneStreetAddressModValue] ON [EmsEvent].[Scene].[SceneID] = [EmsEvent].[SceneStreetAddressModValue].[SceneID]
    LEFT JOIN [GlobalResource].[IncidentStreetAddressModifier] ON [EmsEvent].[SceneStreetAddressModValue].[NotValue] = [GlobalResource].[IncidentStreetAddressModifier].[DataElementID]
    LEFT JOIN [GlobalResource].[NotValue] IncidentStreetAddressNotValue ON [GlobalResource].[IncidentStreetAddressModifier].[NotValueID] = IncidentStreetAddressNotValue.[NotValueID]
    LEFT JOIN [EmsEvent].[CustomConfig] on [EmsEvent].[Incident].[IncidentID] = [EmsEvent].[CustomConfig].[IncidentID]
    LEFT JOIN [EmsEvent].[IncidentDisasterType] on [EmsEvent].[Incident].[IncidentID] = [EmsEvent].[IncidentDisasterType].[IncidentID]
    LEFT JOIN [EmsEvent].[Response] on [EmsEvent].[Scene].[SceneID] = [EmsEvent].[Response].[SceneID]
    LEFT JOIN [EmsEvent].[CrewMember] on [EmsEvent].[Response].[ResponseID] = [EmsEvent].[CrewMember].[ResponseInformationID]

WHERE [EmsEvent].[Incident].[DeletedStatus] = 0
    AND [EmsEvent].[Incident].AgencyID = '607CEE05-276D-49A1-B6BF-FD606EFC2377'
ORDER BY [EmsEvent].[IncidentIncidentNumberModValue].[IncidentNumber] ASC
OFFSET 0 ROWS
FETCH NEXT 25 ROWS ONLY
OPTION(recompile)

1 个答案:

答案 0 :(得分:3)

这取决于您在连接中使用的左外连接表中的哪个列。

如果列是主键或具有唯一约束,则如果查询计划中未在其他位置引用该表,则该表将从查询计划中排除。

看起来你的最后四张表并没有加入各自的主键。

使用这样的表:

create table Parent
(
  ParentID int primary key
)

create table Child
(
  ChildID int primary key,
  ParentID int references Parent(ParentID)
)

此查询不会使用表Parent

select C.*
from Child as C
  left outer join Parent as P
    on P.ParentID = C.ParentID

enter image description here

但是这个查询必须使用左外连接的Child表,因为如果外键上有多个匹配项,它可能会在结果中添加行。

select P.*
from Parent as P
  left outer join Child as C
    on P.ParentID = C.ParentID

enter image description here