SELECT查询中的查找和条件JOIN

时间:2011-03-14 19:54:32

标签: sql sql-server join if-statement

我有一张包含三条患者信息的表格。

Diagnosis_ID      Patient_ID        Diagnosis_Code
====================================================
1                 Jenkins, Sam          A743
2                 Smith, Fred           D638
3                 Doe, John             G732

我想查询此表,但还添加第三列“诊断描述”,该列链接到另一个表中的诊断代码。

Diagnosis_ID      Patient_ID        Diagnosis_Code     Diagnosis_Description
=============================================================================
1                 Jenkins, Sam          A743             Sleep Apnea
2                 Smith, Fred           D638             High Blood Pressure
3                 Doe, John             G732             Dislocated Joint

通常情况下,JOIN可以Diagnosis_CodeDiagnosis_DescriptionDiagnosis_Description相关的表格,我会很高兴。然而,这并不容易。 SELECT DiagnosisLevel FROM DiagnosisDetail WHERE Diagnosis_ID = 1 If DiagnosisLevel = "DiagnosisTable1" Then SELECT Diagnosis_Description FROM DiagnosisTable1 WHERE Diagnosis_Code = 'A743' ElseIf DiagnosisLevel = "DiagnosisTable2" Then SELECT Diagnosis_Description FROM DiagnosisTable2 WHERE Diagnosis_Code = 'A743' ElseIf SELECT Diagnosis_Description FROM DiagnosisTable3 WHERE Diagnosis_Code = 'A743' End If 的值位于三个可能表中的一个中。确定我需要加入哪个表取决于Diagnosis_ID是什么。

所以我当前要做的就是每个Diagnosis_ID我必须查询另一个表,告诉我哪个表需要基于Diagnosis_Level加入Diagnosis_Code,然后一旦我有了,我就可以得到Diagnosis_Description。这是一些我希望描述过程的“伪代码”。

{{1}}

我不知道如何在SQL中完成所有这些操作。它甚至可能还是我必须在代码中完成所有操作(即C#)?

如果这看起来很模糊,我道歉。我尽力创建一个简单的例子来演示这个问题。我没有设计这个数据库,但必须在其结构中工作。

4 个答案:

答案 0 :(得分:7)

多个LEFT JOIN?对于主表中的每一行,这将选择适当的LEFT JOIN到正确的DiagnosisTable

SELECT
    T.*, 
    COALESCE(D1.Diagnosis_Description, D2.Diagnosis_Description, D3.Diagnosis_Description)
FROM 
    MyTable T
    LEFT JOIN
    DiagnosisTable1 D1 ON T.Diagnosis_Code = D1.Diagnosis_Code
                   AND T.DiagnosisLevel = 'DiagnosisTable1'
    LEFT JOIN
    DiagnosisTable2 D2 ON T.Diagnosis_Code = D2.Diagnosis_Code
                   AND T.DiagnosisLevel = 'DiagnosisTable2'
    LEFT JOIN
    DiagnosisTable3 D3 ON T.Diagnosis_Code = D3.Diagnosis_Code
                   AND T.DiagnosisLevel = 'DiagnosisTable3'

答案 1 :(得分:2)

让我们打电话给你的第一张病人患者_诊断。如果Diagnosis_code仅出现在三个诊断表中的一个

中,我将采用第一种方法
select
  aa.Diagnosis_ID,
  aa.Patient_ID,
  aa.Diagnosis_Code,
  coalesce(bb.Diagnosis_Description,    cc.Diagnosis_Description,  
    dd.Diagnosis_Description)     as    Diagnosis_Description
from
  patient_diagnosis as aa
left join
  DiagnosisTable1 as bb on aa.Diagnosis_Code = bb.Diagnosis_Code
left join
  DiagnosisTable2 as cc on aa.Diagnosis_Code = cc.Diagnosis_Code
left join
  DiagnosisTable3 as dd on aa.Diagnosis_Code = dd.Diagnosis_Code

第二个是类似的,但实际上使用了查找表

select
  aa.Diagnosis_ID,
  aa.Patient_ID,
  aa.Diagnosis_Code,
  case when ee.Diagnosis_Level = 1 then bb.Diagnosis_Description
  when ee.Diagnosis_Level = 2 then cc.Diagnosis_Description
  when ee.Diagnosis_Level = 3 then dd.Diagnosis_Description
  else 'Error' end as    Diagnosis_Description
from
  patient_diagnosis as aa
left join
  DiagnosisTable1 as bb on aa.Diagnosis_Code = bb.Diagnosis_Code
left join
  DiagnosisTable2 as cc on aa.Diagnosis_Code = cc.Diagnosis_Code
left join
  DiagnosisTable3 as dd on aa.Diagnosis_Code = dd.Diagnosis_Code
join
  DiagnosisDetail as ee on aa.Diagnosis_ID = ee.Diagnosis_ID

答案 2 :(得分:1)

您可以虚拟地合并所有3个诊断级别表,然后加入它。如果必须有匹配,请将LEFT更改为INNER JOIN,否则LEFT JOIN不会受到伤害。

SELECT A.Diagnosis_ID, A.Patient_ID, A.Diagnosis_Code, B.Diagnosis_Description
FROM Diagnosis A
left join
(
    SELECT DiagnosisLevel = 'DiagnosisTable1', Diagnosis_Code, Diagnosis_Description
    FROM DiagnosisTable1
    UNION ALL
    SELECT DiagnosisLevel = 'DiagnosisTable2', Diagnosis_Code, Diagnosis_Description
    FROM DiagnosisTable2
    UNION ALL
    SELECT DiagnosisLevel = 'DiagnosisTable3', Diagnosis_Code, Diagnosis_Description
    FROM DiagnosisTable3
) B on A.Diagnosis_Level = B.DiagnosisLevel and A.Diagnosis_Code = B.Diagnosis_Code

虽然这看起来很像是一项昂贵的操作,但它实际上非常有效。所有带有拆分列(DiagnosisLevel)的UNION都是一种分区策略,SQL Server仅使用它来选择需要查看的表。例如,这是一个测试。

create table Diagnosis(
    Diagnosis_ID int primary key, 
    Patient_ID varchar(100), 
    Diagnosis_Code varchar(10), 
    Diagnosis_Level varchar(100))
insert Diagnosis select
    '1' ,'Jenkins, Sam' ,'A743','DiagnosisTable1' union all select
    '2' ,'Smith, Fred' ,'D638','DiagnosisTable2' union all select
    '3' ,'Doe, John' ,'G732','DiagnosisTable3'
create table DiagnosisTable1(id int identity primary key,Diagnosis_Code varchar(10),Diagnosis_Description varchar(100))
create index ix_DiagnosisTable1 on DiagnosisTable1(Diagnosis_Code) include (Diagnosis_Description)
insert DiagnosisTable1 select
    'A748', 'Sleep Apnea 1' union all select
    'A745', 'Sleep Apnea 2' union all select
    'A746', 'Sleep Apnea 3' union all select
    'A743', 'Sleep Apnea'
insert DiagnosisTable1 select top 1000
    Diagnosis_Code + left(CONVERT(varchar(max), newid()),3),
    Diagnosis_Description + CONVERT(varchar(max), newid())
from DiagnosisTable1 cross join master..spt_values
create table DiagnosisTable2(id int identity primary key,Diagnosis_Code varchar(10),Diagnosis_Description varchar(100))
create index ix_DiagnosisTable2 on DiagnosisTable2(Diagnosis_Code) include (Diagnosis_Description)
insert DiagnosisTable2 select
    'D6381', 'High Blood Pressure 1' union all select
    'D638', 'High Blood Pressure 3' union all select
    'D6384', 'High Blood Pressure'
insert DiagnosisTable2 select top 1000
    Diagnosis_Code + left(CONVERT(varchar(max), newid()),3),
    Diagnosis_Description + CONVERT(varchar(max), newid())
from DiagnosisTable2 cross join master..spt_values
create table DiagnosisTable3(id int identity primary key,Diagnosis_Code varchar(10),Diagnosis_Description varchar(100))
create index ix_DiagnosisTable3 on DiagnosisTable3(Diagnosis_Code) include (Diagnosis_Description)
insert DiagnosisTable3 select
    'G732', 'HDislocated Jointe 1' union all select
    'D6X8', 'HDislocated Joint 3' union all select
    'GGG84', 'Dislocated Joint'
insert DiagnosisTable3 select top 1000
    Diagnosis_Code + left(CONVERT(varchar(max), newid()),3),
    Diagnosis_Description + CONVERT(varchar(max), newid())
from DiagnosisTable3 cross join master..spt_values

==========
Summary
==========
3x diagnosis records
4000, 3000 and 3000 records in each of the level 1,2,3 tables

查询(从上面重复)

SELECT A.Diagnosis_ID, A.Patient_ID, A.Diagnosis_Code, B.Diagnosis_Description
FROM Diagnosis A
left join
(
    SELECT DiagnosisLevel = 'DiagnosisTable1', Diagnosis_Code, Diagnosis_Description
    FROM DiagnosisTable1
    UNION ALL
    SELECT DiagnosisLevel = 'DiagnosisTable2', Diagnosis_Code, Diagnosis_Description
    FROM DiagnosisTable2
    UNION ALL
    SELECT DiagnosisLevel = 'DiagnosisTable3', Diagnosis_Code, Diagnosis_Description
    FROM DiagnosisTable3
) B on A.Diagnosis_Level = B.DiagnosisLevel and A.Diagnosis_Code = B.Diagnosis_Code

执行计划

Plan overview

<小时/> Expanded

答案 3 :(得分:0)

你实际上已经非常接近了

在您的选择中只需执行此操作

Select 
    Diagnosis_ID,
    Patient_ID,
    Diagnosis_Code,
    (Case
     When Level.DiagnosisLevel = "DiagnosisTable1" Then
        SELECT Diagnosis_Description FROM DiagnosisTable1 
     When Level.DiagnosisLevel = "DiagnosisTable2" Then
        SELECT Diagnosis_Description FROM DiagnosisTable2 
     When Level.DiagnosisLebel = "DiagnosisTable3" Then
     --Or you could just do an Else
        SELECT Diagnosis_Description FROM DiagnosisTable3 
     End) As Diagnosis_Description
    From MainTable
    Join TableThatHasLevels As Level ON Level.Diagnosis_Code = Diagnosis_Code

您应该能够加入获取诊断表信息的查询并执行该操作