问题
I am working on an application that allows users to dynamically choose what they see. The list of columns and tables those belong to is huge. I'm working on building a dynamic query but I don't want to have to store all the join logic if I don't have too. An example is I have a query that has LEFT JOINS for 10 tables but I only select and filter by one table. Is SQL Server 2012 Smart enough to not join on the other tables that are not needed?
I know Oracle's DBMS works like this but my company uses SQL Server 2012 so I'm stuck with that.
Example Query where the last 4 LEFT JOINS don't need to be performed:
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:
It depends on what column in the left outer joined table you are using in the join.
If the column is a primary key or has a unique constraint the table will be excluded from the query plan if it is not referenced elsewhere in the query.
It does not look like your last four tables are joined on their respective primary key.
With tables like this:
create table Parent
(
ParentID int primary key
)
create table Child
(
ChildID int primary key,
ParentID int references Parent(ParentID)
)
This query will not use the table Parent
.
select C.*
from Child as C
left outer join Parent as P
on P.ParentID = C.ParentID

But this query have to use the left outer joined Child table because it might add rows to the result if there are more than one hit on the foreign key.
select P.*
from Parent as P
left outer join Child as C
on P.ParentID = C.ParentID

来源:https://stackoverflow.com/questions/20434556/does-sql-server-2012-lazy-join