用于 4 个表的 SQL Server 2008 连接类型

Posted

技术标签:

【中文标题】用于 4 个表的 SQL Server 2008 连接类型【英文标题】:SQL Server 2008 Join type to use for 4 tables 【发布时间】:2015-01-28 22:27:00 【问题描述】:

我有一个由 MS Access 中的同事创建的患者实验室数据库,该数据库有 4 个表。

表 1 包含患者人口统计数据(患者 ID、性别、出生日期等)

表 2 包含 Type1(血压、心率)

表 3 包含 Type2(化学面板、血红蛋白等)

表4包含Type3(微生物培养结果)

每个表都有一个共同的内部患者编号。每项措施都可以独立于其他措施进行,并且可能有结果,也可能没有结果。我想要的是一个简单的表,它提取了仅在表 1 中找到的外部患者 ID、性别和出生日期,并结合了其他每个表的结果的日期。我尝试使用 RIGHT 连接,并希望在后续表中的日期不匹配时会有“空”值。相反,我有一个看起来像交叉表查询的结果,每一行都有一个值。显然我没有正确理解 JOINS 的使用。这是我尝试过的:

SET DATEFORMAT dmy
DECLARE @time time(0)

Select DISTINCT
P.PATIENT_ID as 'Patient ID',
P.SEX as 'Sex',
CONVERT(VARCHAR(11),P.DOB) as 'DOB',
CONVERT(VARCHAR,TYPE1.DateTime,101)as 'BP Measure DATES',
CONVERT(VARCHAR,TYPE2.DateTime,101) as 'CHEM Measure DATES',
CONVERT(VARCHAR,TYPE3.DateTime,101) as 'MICRO Measure DATES'
From dbo.PATIENT as P LEFT JOIN dbo.BRACHIALBPS as TYPE1 on P.PATIENT_NO=TYPE1.PATIENT_NO
Right Join dbo.Chemistries as TYPE2 on P.PATIENT_NO=TYPE2.PATIENT_NO
Right Join dbo.Microbiologies as TYPE3 on P.PATIENT_NO=TYPE3.PATIENT_NO
ORDER BY P.PATIENT_ID

我正在使用 SQL Server 2008 导入数据并执行查询。

正如我所提到的,我希望每个患者/每个结果日期有一行。 但是对于每个日期组合,我都会得到多行。

提前感谢您的指导!

【问题讨论】:

【参考方案1】:

请尝试以下版本的查询:

SET DATEFORMAT dmy
DECLARE @time time(0)

Select DISTINCT
    P.PATIENT_ID as 'Patient ID',
    P.SEX as 'Sex',
    CONVERT(VARCHAR(11),P.DOB) as 'DOB',
    CONVERT(VARCHAR,TYPE1.DateTime,101)as 'BP Measure DATES',
    CONVERT(VARCHAR,TYPE2.DateTime,101) as 'CHEM Measure DATES',
    CONVERT(VARCHAR,TYPE3.DateTime,101) as 'MICRO Measure DATES'
From 
    dbo.PATIENT as P 
    LEFT JOIN dbo.BRACHIALBPS as TYPE1 
        on P.PATIENT_NO=TYPE1.PATIENT_NO
    LEFT Join dbo.Chemistries as TYPE2 
        on P.PATIENT_NO=TYPE2.PATIENT_NO
    LEFT Join dbo.Microbiologies as TYPE3 
        on P.PATIENT_NO=TYPE3.PATIENT_NO
ORDER BY 
    P.PATIENT_ID

右连接已替换为左连接。

当查询中有RIGHT JOIN dbo.BRACHIALBPS as TYPE1 on P.PATIENT_NO=TYPE1.PATIENT_NO 时,它“告诉”数据库引擎从dbo.BRACHIALBPS as TYPE1 表中获取所有适用的(未过滤掉的)行,并尝试在表dbo.PATIENT as P 中找到匹配的行 - 如果匹配没有找到,用 NULL 填充特定结果记录的表 P 的“缺失字段”。

使用左连接将优先考虑dbo.PATIENT as P,因此连接过程中的行首先从该表中获取,然后尝试在左连接表dbo.BRACHIALBPS as TYPE1中找到匹配。同样,如果没有匹配项 - 查询结果中 TYPE1 中的“缺失字段”将用 NULL 填充。

关于 SO 有一个有趣的帖子,其中 JOINS 被非常详细地解释并且从很多方面 - 请看:Difference between INNER and OUTER joins

我希望我正确理解了这个问题,并且至少有一点帮助。

【讨论】:

谢谢T_G,我会给你一个赞成票,但作为一个苦工,我还不能!这对我帮助很大。它比我的原版效果更好,但我仍然需要对其进行更多调整。当我分别运行每个查询时,每组只有大约 35 个日期(类型 1、类型 2、类型 3)。但是当我按照你的建议运行查询时,我有 174 个结果。它仍在匹配匹配日期的所有可能变化。我想我要么需要根据日期运行查询,要么加入子查询。但是,你绝对给了我前进的方向! 没问题 :) 。但它对你有帮助吗? 我很高兴能帮上一点忙。如果我带来了一些可能有用的东西,我会写。问候。【参考方案2】:

对此进行了更多处理,我使用了临时表并将它们连接起来以获得我需要的结果。不确定是否有更好或更有效的方法,但它确实有效。如果对我所做的事情有任何意见或疑虑,很想听听意见。

SET DATEFORMAT dmy
DECLARE @time time(0)

Select DISTINCT 
PATIENT.PATIENT_ID as 'PatientID',
PATIENT.SEX as 'Sex',
CONVERT(VARCHAR(11),PATIENT.DOB) as 'DOB'
INTO #PAT
From PATIENT

SELECT DISTINCT
P.PATIENT_ID as 'PatientID',
CONVERT(VARCHAR,TYPE1.DateTime,101)as 'BP Measure DATES'
INTO #BP
FROM dbo.PATIENT as P Inner JOIN dbo.BRACHIALBPS as TYPE1 on P.PATIENT_NO=TYPE1.PATIENT_NO

SELECT DISTINCT
P.PATIENT_ID as 'PatientID',
CONVERT(VARCHAR,TYPE2.DateTime,101) as 'CHEM Measure DATES'
INTO #CHEM
FROM dbo.PATIENT as P Inner JOIN dbo.Chemistries as TYPE2 on P.PATIENT_NO=TYPE2.PATIENT_NO

SELECT DISTINCT
P.PATIENT_ID as 'PatientID', 
CONVERT(VARCHAR,TYPE3.DateTime,101) as 'MICRO Measure DATES'
INTO #MIC
From dbo.PATIENT as P Inner JOIN dbo.Microbiologies as TYPE3 on P.PATIENT_NO=TYPE3.PATIENT_NO

SELECT DISTINCT
#PAT.PatientID,
#PAT.DOB,
#PAT.Sex,
#BP.[BP Measure DATES],
#CHEM.[CHEM Measure DATES],
#MIC.[MICRO Measure DATES]
FROM #PAT
Left JOIN #BP on #PAT.PATIENTID=#BP.PATIENTID
Left Join #CHEM on #PAT.PatientID=#CHEM.PatientID and #BP.[BP Measure DATES]=#CHEM.[CHEM Measure DATES]
Left Join #MIC on #PAT.PatientID=#MIC.PatientID and #BP.[BP Measure DATES]=#MIC.[MICRO Measure DATES]

【讨论】:

以上是关于用于 4 个表的 SQL Server 2008 连接类型的主要内容,如果未能解决你的问题,请参考以下文章

sql server 2008 数据库图表 表名搜索

用sqlserver2008创建了1个表,里面有几个属性,其中一个属性我不想要了,怎么删除,

视图中四个表的 SQL Server 条件连接

如何在 SQL Server 2008 上创建插入更新触发器

带有 2 个表的 SQL Server GROUP BY

sql server 语句如何将3个表合并成一个表?