【问题标题】:SQL Duplicate Rows Multiple JoinsSQL重复行多个连接
【发布时间】:2016-06-11 00:25:12
【问题描述】:

对于 SQL,我几乎是个菜鸟,因此我们将不胜感激。我有一个大型数据集,我正在为医院过滤。我从 6 个不同的表中提取数据,我的一个表每次访问都有重复的行。我只想为每次访问拉一行(拉到哪一行都没有关系)。我知道我需要使用 DISTINCT 或 GROUP BY 子句,但我的语法一定是错误的。

    SELECT
         ADV.[VisitID]          AS  VisitID
        ,ADV.[Name]             AS  Name
        ,ADV.[UnitNumber]       AS  UnitNumber
        ,CONVERT(DATE,ADV.[BirthDateTime])                          AS  BirthDate
        ,ADV.[ReasonForVisit]   AS  ReasonForVisit
        ,ADV.[AccountNumber]    AS  AccountNumber
        ,DATEDIFF(day, ADV.ServiceDateTime, DIS.DischargeDateTime)  AS LOS
        ,ADV.[HomePhone]        AS  PhoneNumber
        ,ADV.[ServiceDateTime]  AS  ServiceDateTime
        ,ADV.[Status]           AS  'Status'
        ,PRV.[PrimaryCareID]    AS  PCP
        ,LAB.[TestMnemonic]     AS  Test
        ,LAB.[ResultRW]         AS  Result
        ,LAB.[AbnormalFlag]     AS  AbnormalFlag
        ,LAB.[ResultDateTime]   AS  ResultDateTime
        ,DIS.[Diagnosis]        AS  DischargeDiagnosis
        ,DIS.[ErDiagnosis]      AS  ERDiagnosis
        ,DCP.[TextLine]         AS  ProblemList


FROM          Visits                                      ADV
    LEFT JOIN Tests                                       LAB             ON ( LAB.VisitID  = ADV.VisitID AND
                                                                               LAB.SourceID = ADV.SourceID )
    LEFT JOIN Discharge                                   DIS             ON ( DIS.VisitID  = LAB.VisitID AND
                                                                               DIS.SourceID = LAB.SourceID )
    LEFT JOIN Providers                                   PRV             ON ( PRV.VisitID  = DIS.VisitID AND
                                                                               PRV.SourceID = DIS.SourceID )
    LEFT JOIN ProblemListVisits                           EPS             ON ( EPS.VisitID  = PRV.VisitID AND
                                                                               EPS.SourceID = PRV.SourceID )                                                                                                 
    LEFT JOIN ProblemList                                 DCP             ON ( DCP.PatientID = EPS.PatientID AND
                                                                               DCP.SourceID  = EPS.SourceID )


WHERE ( DCP.[TextLine]       LIKE '%Diabetes%'          OR 
        DCP.[TextLine]       LIKE '%Diabetic%'          OR
        DCP.[TextLine]       LIKE '%DM2%'               OR
        DCP.[TextLine]       LIKE '%DKA%'               OR
        DCP.[TextLine]       LIKE '%Hyperglycemia%'     OR
        DCP.[TextLine]       LIKE '%Hypoglycemia%'    ) AND
      ( LAB.[TestMnemonic] = 'GLU'                      OR
        LAB.[TestMnemonic] = '%HA1C'                  ) AND
        ADV.[Status]      != 'DIS CLI'                )

所以这可以正常工作,但是当医生进入患者的问题列表并进行更改时,它会重新归档整个列表,从而再次填充问题列表表。因此,对于 1 次访问,由于 ProblemList,我可能会获得 4 个重复条目,而我只想要一个。哪一个也无所谓。

我尝试引用其他问题并在其中嵌套另一个 SELECT 语句,但我不断收到语法错误。

这是重复值的样子:

1111111111  SMITH,JOHN  1111    1/1/1901    CHEST PAIN  1111    2   111-111-1111    1/1/1901 12:15  DIS IN  DOEJO   GLU 120  H  1/2/1901 6:35   NULL    CHEST PAIN  Diabetes type 2, controlled
1111111111  SMITH,JOHN  1111    1/1/1901    CHEST PAIN  1111    2   111-111-1111    1/1/1901 12:15  DIS IN  DOEJO   GLU 120  H  1/2/1901 6:35   NULL    CHEST PAIN  Diabetes type 2, controlled
1111111111  SMITH,JOHN  1111    1/1/1901    CHEST PAIN  1111    2   111-111-1111    1/1/1901 12:15  DIS IN  DOEJO   GLU 120  H  1/2/1901 6:35   NULL    CHEST PAIN  Diabetes type 2, controlled
1111111111  SMITH,JOHN  1111    1/1/1901    CHEST PAIN  1111    2   111-111-1111    1/1/1901 12:15  DIS IN  DOEJO   GLU 120  H  1/2/1901 6:35   NULL    CHEST PAIN  Diabetes type 2, controlled

最后,“2 型糖尿病,受控”是导致重复的原因。如果我从查询中删除 ProblemListVisit 和 ProblemList 表,我只会得到一行数据。

最重要的是获得所有独特的测试结果,但不是问题列表的所有重复条目(只想知道他们患有哪种类型的糖尿病,ONCE)。

谢谢!

【问题讨论】:

  • 要获得不同,您只需将单词 distinct 放在单词 select 旁边,然后按原样运行查询。最好找出为什么有重复项。据推测,problemlistvisit 和problemlist 表中的某些值未显示在选择列表中,但它们并没有区别。通过select * 并找出导致“重复”的值来更好地追踪它们
  • 在将 DISTINCT 投入其中之前,我会尝试找出真正问题的根源。选择所有列 SELECT *... 并在其他重复的行中查找不同的列,这将是一个很好的故障排除步骤。
  • 正如@dan08 所说,但我最感兴趣的是ProblemList 表中重复的性质,而不是查询结果,因为前者驱动后者。
  • 您的连接看起来很可疑。几乎所有内容都通过相同的VisitIDSourceID 连接,但看起来所有表都以对应于连接的方式相关联。此外,ProblemList 表 not 是否像所有其他表一样具有 VisitID 列?如果有,那么您在加入该表时可能需要考虑到这一点。
  • 谢谢大家!我知道为什么会有重复。不幸的是,每次医生提交问题列表时,它都会创建一个新条目,该条目附加到相同的PatientID,从而创建了重复项。 @John:ProblemList 表没有VisitID,这是正确的。这就是为什么我必须先加入 ProblemListVisit 表,该表同时包含 VisitIDPatientID @paqogomez:没有意识到 Distinct 这么简单!谢谢,效果很好。

标签: sql duplicates left-join


【解决方案1】:

代替DISTINCT,我认为这是实现这一目标的最快方法,您还可以将生成多行的每个表移动到子查询中,在该子查询中,您可以根据您为 JOINS 和 SELECTS 寻找的值进行分组.

这里有两个优点:

  1. 您可以更好地控制这些更精细的表格的输出,并且

  2. 当您使用子查询中的 WHERE 子句限制它们允许的内容时,您可以减少 JOIN 的开销,这将减少您的 I/O 和 CPU 使用率。

代码:

SELECT
         ADV.[VisitID]          AS  VisitID
        ,ADV.[Name]             AS  Name
        ,ADV.[UnitNumber]       AS  UnitNumber
        ,CONVERT(DATE,ADV.[BirthDateTime])                          AS  BirthDate
        ,ADV.[ReasonForVisit]   AS  ReasonForVisit
        ,ADV.[AccountNumber]    AS  AccountNumber
        ,DATEDIFF(day, ADV.ServiceDateTime, DIS.DischargeDateTime)  AS LOS
        ,ADV.[HomePhone]        AS  PhoneNumber
        ,ADV.[ServiceDateTime]  AS  ServiceDateTime
        ,ADV.[Status]           AS  'Status'
        ,PRV.[PrimaryCareID]    AS  PCP
        ,LAB.[TestMnemonic]     AS  Test
        ,LAB.[ResultRW]         AS  Result
        ,LAB.[AbnormalFlag]     AS  AbnormalFlag
        ,LAB.[ResultDateTime]   AS  ResultDateTime
        ,DIS.[Diagnosis]        AS  DischargeDiagnosis
        ,DIS.[ErDiagnosis]      AS  ERDiagnosis
        ,DCP.[TextLine]         AS  ProblemList


FROM          Visits                                      ADV
    LEFT JOIN Tests                                       LAB             ON ( LAB.VisitID  = ADV.VisitID AND
                                                                               LAB.SourceID = ADV.SourceID )
    LEFT JOIN Discharge                                   DIS             ON ( DIS.VisitID  = LAB.VisitID AND
                                                                               DIS.SourceID = LAB.SourceID )
    LEFT JOIN Providers                                   PRV             ON ( PRV.VisitID  = DIS.VisitID AND
                                                                               PRV.SourceID = DIS.SourceID )
    LEFT JOIN 
        (
            SELECT 
                VisitID, 
                SourceID, 
                PatientID
            FROM ProblemListVisits 
            GROUP BY 
                VisitID, 
                SourceID, 
                PatientID
        )                                                 EPS             ON ( EPS.VisitID  = PRV.VisitID AND
                                                                               EPS.SourceID = PRV.SourceID )                                                                                                 
    LEFT JOIN 
        (
            SELECT 
                PatientID, 
                SourceID, 
                TextLine 
            FROM ProblemList 
            WHERE 
                [TextLine]       LIKE '%Diabetes%'          OR 
                [TextLine]       LIKE '%Diabetic%'          OR
                [TextLine]       LIKE '%DM2%'               OR
                [TextLine]       LIKE '%DKA%'               OR
                [TextLine]       LIKE '%Hyperglycemia%'     OR
                [TextLine]       LIKE '%Hypoglycemia%' 
            GROUP BY 
                PatientID, 
                SourceID, 
                TextLine 
        )                                                  DCP             ON ( DCP.PatientID = EPS.PatientID AND
                                                                               DCP.SourceID  = EPS.SourceID )


WHERE ( LAB.[TestMnemonic] = 'GLU'                      OR
        LAB.[TestMnemonic] = '%HA1C'                  ) AND
        ADV.[Status]      != 'DIS CLI'                )

如果您仍然得到倍数,则表明 [TextLine] 对于您的 ProblemList 表中的每个 VisitID/PatientID 组合具有多个值。此时,您可以从 GROUP BY 子句中删除该字段,并在子查询中对该字段使用某种聚合,例如 MAX([TextLine])。不过,我怀疑在使用 DISTINCT 或使用此子查询方法后您不会有重复项。

【讨论】:

  • 你的代码太棒了!非常感谢。我将此作为答案,因为它比仅使用Distinct 快了整整 20 秒。唯一的问题是,我得到了 [TextLine] 的 NULL 值以及子查询的 WHERE 子句中定义的值。所以我只是在ADV.[Status] != 'DIS CLI' 之后的主查询末尾添加了:WHERE DCP.[TextLine] IS NOT NULL ) ,它就像一个魅力。感谢您为我整理这些内容,这对我有很大帮助!
  • 我刚刚阅读了这个答案,并意识到我遗漏了 AND DCP.[TextLine] IS NOT NULL 条件来复制原始查询的相同输出。对不起,我错过了。
  • 也忘了提到我必须在 GROUP BY 子句中使用实际的列名而不是数字。所以它是GROUP BY [PatientID],[SourceID],[TextLine] 和上面一样。另外,请注意,第一个子查询中不应有额外的SourceID。再次感谢代码@JNevill
【解决方案2】:

Distinct 子句应该可以解决问题 但如果不是你可以改变

LEFT JOIN ProblemList   DCP             ON ( DCP.PatientID = EPS.PatientID AND
                                             DCP.SourceID  = EPS.SourceID )

OUTER APPLY (Select top 1 DCP.[TextLine]  FROM  ProblemList   DCP WHERE
                                             DCP.PatientID = EPS.PatientID  
                                           AND DCP.SourceID  = EPS.SourceID) DCP

【讨论】:

  • 这正是我想要的。我有一个查询,只需添加一个连接,即使没有引用其中的任何内容,也会导致每一行都被直接复制。这个替换解决了这个问题。
【解决方案3】:

尝试在SELECT 之后添加DISTINCT。像这样的:

SELECT DISTINCT
     ADV.[VisitID]          AS  VisitID
    ,ADV.[Name]             AS  Name 
    ...

【讨论】:

    猜你喜欢
    • 2013-04-01
    • 1970-01-01
    • 2018-12-12
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多