If I have this correct, there are a few ways to do joins in T-SQL. One that I use a lot is:select * from foojoin (select * from bar)on foo.key = bar.keyThe other way that I know about is:select * from foo, barwhere foo.key = bar.keyWhile trying this out on a real example, I was surprised to see a difference in the execution plan:e.g.create table #CLOC_RCIP (ticket char(5))insert into #CLOC_RCIPset showplan_text ongoselect convert(char(5), rcip.ticket) from CRS_RCIP_3_month rcipjoin (select * from CRS_cloc_3_month) clocon cloc.ticket = rcip.ticketwhere cloc.Outage != rcip.Outage or cloc.OSF != rcip.OSF
gives the plan: |--Hash Match(Inner Join, HASH:([rcip].[Ticket])=([OR_CRS].[dbo].[CRS_cloc_3_month].[Ticket]), RESIDUAL:([OR_CRS].[dbo].[CRS_RCIP_3_month].[Ticket] as [rcip].[Ticket]=[OR_CRS].[dbo].[CRS_cloc_3_month].[Ticket] AND ([OR_CRS].[dbo].[CRS_cloc_3_month].[Outage]<>[OR_CRS].[dbo].[CRS_RCIP_3_month].[Outage] as [rcip].[Outage] OR [OR_CRS].[dbo].[CRS_cloc_3_month].[OSF]<>[OR_CRS].[dbo].[CRS_RCIP_3_month].[OSF] as [rcip].[OSF]))) |--Compute Scalar(DEFINE:([Expr1007]=CONVERT(char(5),[OR_CRS].[dbo].[CRS_RCIP_3_month].[Ticket] as [rcip].[Ticket],0))) | |--Table Scan(OBJECT:([OR_CRS].[dbo].[CRS_RCIP_3_month] AS [rcip])) |--Table Scan(OBJECT:([OR_CRS].[dbo].[CRS_cloc_3_month]))
Converting the select to the other form:select convert(char(5), rcip.ticket) from CRS_RCIP_3_month rcip, CRS_cloc_3_month clocwhere cloc.ticket = rcip.ticketand cloc.Outage != rcip.Outage or cloc.OSF != rcip.OSF
gives the plan: |--Nested Loops(Inner Join, WHERE:([OR_CRS].[dbo].[CRS_cloc_3_month].[Ticket] as [cloc].[Ticket]=[OR_CRS].[dbo].[CRS_RCIP_3_month].[Ticket] as [rcip].[Ticket] AND [OR_CRS].[dbo].[CRS_cloc_3_month].[Outage] as [cloc].[Outage]<>[OR_CRS].[dbo].[CRS_RCIP_3_month].[Outage] as [rcip].[Outage] OR [OR_CRS].[dbo].[CRS_cloc_3_month].[OSF] as [cloc].[OSF]<>[OR_CRS].[dbo].[CRS_RCIP_3_month].[OSF] as [rcip].[OSF])) |--Compute Scalar(DEFINE:([Expr1006]=CONVERT(char(5),[OR_CRS].[dbo].[CRS_RCIP_3_month].[Ticket] as [rcip].[Ticket],0))) | |--Table Scan(OBJECT:([OR_CRS].[dbo].[CRS_RCIP_3_month] AS [rcip])) |--Table Spool |--Table Scan(OBJECT:([OR_CRS].[dbo].[CRS_cloc_3_month] AS [cloc]))
Now I'd like to know, why the difference? And, would I see a meaningful performance difference between the two?