sql - 将非标准联接转换为标准联接

标签 sql sql-server sql-server-2008 sybase

我正在尝试重新处理查询,以便它使用标准连接(在 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%')

最佳答案

问题在于,左联接会为未找到匹配行的联接列值返回空值,但您正在 where 子句中检查这些列值,但 where 谓词所有行连接后执行,因此它们永远不会匹配并且您的外部连接被沉没。

即这个示例查询:

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

永远不会返回在 table2 中没有相应行的任何行,因为 col1 将为 null,并且与 null 的比较始终为 false,除了 col1 为 null

要解决此问题,您需要将测试移动到 ON 子句中,以便在进行联接时进行比较,如下所示:

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

现在,左连接在键匹配时仍会返回行,并应用额外的谓词进一步细化匹配。


在你的例子中,你正在做一个外部(即 left)连接到 ProcedureCodeMH 作为 PCMH,但是在 中测试 PCMH 的列>WHERE 子句,类似于上面的第一个示例。

您的查询的重写将是(请参阅行内评论以了解更改的位置):

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 是默认的连接类型。

关于sql - 将非标准联接转换为标准联接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11769203/

相关文章:

SQL 删除 TOP 语句

sql - 检查 SQL 表列中数据的可用性?

sql - 如何从一个变量获取同一天和同一月的日期,但根据另一个变量获取同一年的日期?

mysql - mysql存储过程中的错误日期值错误

sql - SQL 中的 'S' 是否代表 "standard"或 "structured"?

sql - AND/OR 运算符未按需要进行过滤

mysql - MYSQL中如何从Varchar字段中选择Max Numeric

sql - 如何在 SQL Server 中获取明细表记录作为字符串

sql-server - tablix 'Tablix1' 无效。缺少 DataSetName 属性的值

sql - 根据另一列的不同值聚合一列