I am trying to rework a query so that it uses standard joins (in from clause) and not the old version (migrating to SQL server so forced to do this conversion). The problem I am running into is that my version of the query below returns a lot fewer records than the original. So I am thinking one of my outer joins isn’t so outer. Thanks for any help, especially if you actually make it through the whole query. I can’t seem to find any good documentation on how to make a transition like this.
declare
@startdate datetime, @enddate datetime
select @startdate = dateadd(dd,-6,convert(datetime,convert(varchar,getdate(),101)))
select @enddate = dateadd(dd,6,@startdate)
SELECT PAT.CUSID as ID ,
substring(CPTREC.CompletedDateTime,1,12) AS DateOfService,
SUBSTRING(PCMH.ProcedureCode,CHARINDEX('-',PCMH.ProcedureCode)+ 1,50) AS CPT_Code
FROM cpt_records as CPTREC
left Outer Join ProcedureCodeMH as PCMH
on CPTREC.ProcedureCodeRevCount = PCMH.ProcedureCodeRevCount
and CPTREC.ProcedureCodeSer= PCMH.ProcedureCodeSer
left outer join Credit as CR
on CPTREC.ActInstProcCodeSer = CR.ActInstProcCodeSer
and CPTREC.ActInstProcCodeRevCount = CR.ActInstProcCodeRevCount
inner join ActivityInstance as ACTIN
on CPTREC.ActivityInstanceSer= ACTIN.ActivityInstanceSer
and CPTREC.ActivityInstanceRevCount = ACTIN.ActivityInstanceRevCount
inner join ActivityCapture as ACTCAP
on ACTCAP.ActivityInstanceSer= ACTIN.ActivityInstanceSer
and ACTCAP.ActivityInstanceRevCount = ACTIN.ActivityInstanceRevCount
inner join ActCaptDiagnosisMH as ACTCAPDMH
on ACTCAPDMH.ActivityCaptureSer = ACTCAP.ActivityCaptureSer
and ACTCAPDMH.ActivityCaptureRevCount=ACTCAP.ActivityCaptureRevCount
left outer join Department as DEPT
on ACTCAP.DepartmentSer = DEPT.DepartmentSer
left outer join Hospitality as HOSP
on DEPT.HospitalitySer = HOSP.HospitalitySer
Left outer join Diagnosis as DIAG
on ACTCAPDMH.DiagnosisSer = DIAG.DiagnosisSer
inner join TemplateCycle as TEMPCYC
on ACTIN.TemplateCycleSer= TEMPCYC.TemplateCycleSer
inner join Template as PLATE
on TEMPCYC.TemplateSer = PLATE.TemplateSer
inner join Patent as PAT
on PLATE.PatentSer = PAT.PatentSer
Left Outer Join PatentParticular as PATPAR
on PAT.PatentSer = PATPAR.PatentSer
inner join PatentDoctor as PATDOC
on PAT.PatentSer = PATDOC.PatentSer
inner join Doctor as DOC
on PATDOC.ResourceSer = DOC.ResourceSer
WHERE ( CPTREC.CompletedDateTime >= @startdate )
and ( CPTREC.CompletedDateTime < dateadd(dd,1,@enddate) )
and ( CPTREC.ObjectStatus = 'Active' )
and ( PATDOC.OncologistFlag = 0 )
and ( PATDOC.PrimaryFlag = 1 )
and ( PCMH.ProcedureCode like '%77781%'
or PCMH.ProcedureCode like '%77782%'
or PCMH.ProcedureCode like '%77783%'
or PCMH.ProcedureCode like '%77784%'
or PCMH.ProcedureCode like '%77785%'
or PCMH.ProcedureCode like '%77786%'
or PCMH.ProcedureCode like '%77787%')
the origional that brings back more records is
SELECT PAT.CUSID as ID , substring(cpt_records.CompletedDateTime,1,12) AS DateOfService, SUBSTRING(ProcedureCodeMH.ProcedureCode,CHARINDEX('-',ProcedureCodeMH.ProcedureCode)+ 1,50) AS CPT_Code INTO cpt777 FROM cpt_records , ActivityCapture , ActivityInstance , Patent as PAT, ProcedureCodeMH , Template , TemplateCycle , Department , Hospitalityity , Credit , Doctor, PatentDoctor , ActCaptDiagnosisMH , Diagnosis , PatentParticular WHERE ( #cpt_records.ProcedureCodeSer *= ProcedureCodeMH.ProcedureCodeSer) and
( ProcedureCodeMH.ProcedureCodeRevCount =*cpt_records.ProcedureCodeRevCount) and
( ActivityCapture.DepartmentSer *= Department.DepartmentSer) and
( Department.HospitalitySer *= Hospitality.HospitalitySer) and
( ActivityCapture.ActivityCaptureSer *= Credit.ActivityCaptureSer) and
( ActivityCapture.ActivityCaptureRevCount *= Credit.ActivityCaptureRevCount) and
( Credit.ActInstProcCodeSer =* cpt_records.ActInstProcCodeSer) and
( Credit.ActInstProcCodeRevCount =* cpt_records.ActInstProcCodeRevCount) and
( Patent.PatentSer *= PatentParticular.PatentSer) and
( cpt_records.ActivityInstanceSer = ActivityInstance.ActivityInstanceSer ) and
(cpt_records.ActivityInstanceRevCount = ActivityInstance.ActivityInstanceRevCount ) and
( ActivityInstance.ActivityInstanceSer = ActivityCapture.ActivityInstanceSer ) and
( ActivityInstance.ActivityInstanceRevCount = ActivityCapture.ActivityInstanceRevCount ) and
( Patent.PatentSer = Template.PatentSer ) and
( Template.TemplateSer = TemplateCycle.TemplateSer ) and
( TemplateCycle.TemplateCycleSer = ActivityInstance.TemplateCycleSer ) and
( Patent.PatentSer = PatentDoctor.PatentSer ) and
( PatentDoctor.ResourceSer = Doctor.ResourceSer ) and
( ActivityCapture.ActivityCaptureSer = ActCaptDiagnosisMH.ActivityCaptureSer ) and
( ActivityCapture.ActivityCaptureRevCount = ActCaptDiagnosisMH.ActivityCaptureRevCount ) and (cpt_records.CompletedDateTime >= @startdate ) and
( cpt_records.CompletedDateTime < dateadd(dd,1,@enddate) ) and
( cpt_records.ObjectStatus = 'Active' ) and
( PatentDoctor.OncologistFlag = 0 ) and
( PatentDoctor.PrimaryFlag = 1 ) and
( ActCaptDiagnosisMH.DiagnosisSer *= Diagnosis.DiagnosisSer) and
( ProcedureCodeMH.ProcedureCode like '%77781%' or ProcedureCodeMH.ProcedureCode like '%77782%' or ProcedureCodeMH.ProcedureCode like '%77783%' or ProcedureCodeMH.ProcedureCode like '%77784%' or ProcedureCodeMH.ProcedureCode like '%77785%' or ProcedureCodeMH.ProcedureCode like '%77786%' or ProcedureCodeMH.ProcedureCode like '%77787%')
The problem is that a left join returns nulls for the joined column values where no matching row is found, but you are checking those column values in the
whereclause, but thewherepredicates are is executed after all the rows are joined, so they’ll never match and your outer joins are sunk.ie, this example query:
will never return any rows that don’t have corresponding rows in
table2, becausecol1will benull, and comparisons withnullare alwaysfalse, except forcol1 is null.To fix this, you need to move the tests into the
ONclause, so the comparison happens while the join is being made, like this:Now the left join will still return rows while matching on the key, and applying extra predicates to further refine the match.
In your case, you are doing an outer (ie
left) join toProcedureCodeMH as PCMH, but testing the columns ofPCMHin theWHEREclause, similar to the first example above.The rewrite of your query would then be (see in-line comment for where the change is):
Note:
inner joincan be simplified to simplyjoin–inneris the default join type.