2012-08-01 141 views
3

我試圖重做一個查詢,以便它使用標準連接(在from子句中)而不是舊版本(遷移到SQL服務器以便強制執行此轉換)。我遇到的問題是我下面的查詢版本返回的記錄比原始記錄少得多。所以我認爲我的一個外連接不是那麼外在。感謝您的幫助,特別是如果您真的通過整個查詢。我似乎無法找到任何有關如何進行這種轉換的良好文檔。將非標準連接轉換爲標準連接

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%') 

是帶回更多的記錄的原始是


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%') 
+0

檢查我對這個問題的回答:[SQL多外連接(轉換t-sql連接到ANSI格式)](http://stackoverflow.com/questions/9501089/sql-multiple-outer-joins-converting- T-SQL-加入到ANSI格式/ 9501490#9501490)。如果3箇舊SQl-Server風格的聯接導致查詢的6種不同變體,8箇舊聯接加上10個內聯接再加上幾個條件將是一個反向工程的地獄。 – 2012-08-02 08:29:38

回答

0

的問題是左連接爲在沒有找到匹配的行的聯接的列值,則返回空值,但您正在檢查where子句中的那些列值,但where謂詞是在執行所有行ar e加入,所以他們永遠不會匹配,你的外部連接被擊沉。

即本例中查詢:

select * 
from table1 t1 
left join table2 t2 on t2.fk = t1.id 
where t2.col1 = 'x' 

永遠返回不具備相應table2行任何行,因爲col1null,並與null比較始終false,除了col1 is null

要解決這個問題,就需要測試移動到ON條款,因此比較發生而join正在取得,像這樣:

select * 
from table1 t1 
left join table2 t2 on t2.fk = t1.id and t2.col1 = 'x' 

現在左連接仍然會返回行同時在關鍵字上進行匹配,並應用額外的謂詞來進一步優化匹配。


在你的情況,你正在做外(即left)加入到ProcedureCodeMH as PCMH,但WHERE條款,類似於上面的第一個例子中的測試PCMH列。

你的查詢重寫將被(見這裏的變化是行註釋):

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 
     -- MOVED THIS TEST FROM WHERE CLAUSE TO HERE 
     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%') 
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 

注:inner join可以簡化爲簡單join - inner是默認的連接類型。