2017-10-12 122 views
0

我在我们的EHR/EMR数据库的SQL上运行查询。我主要看护士在每次患者邂逅/拜访期间完成的评估,并希望返回最近评估日期的答案以及其他一些信息。我创建了查询,并且所有数据都将完成,但是,它将返回所有评估日期和答案,而不仅仅是最新的日期和答案。我将附上下面的完整代码。在SQL查询中选择最近或最近日期

SELECT DISTINCT 
    MAX(PTA.ASSESSMENT_DATE) AS Max_Date, 
    SAQ.QUESTION_TEXT, SAA.ANSWER_TEXT, dbo.PT_BASIC.PATIENT_CODE, 
    dbo.PT_BASIC.NAME_FULL 
FROM 
    dbo.PTC_ASSESSMENT_ANSWER AS PAA 
INNER JOIN 
    dbo.PTC_ASSESSMENT AS PTA ON PTA.ASSESSMENT_ID = PAA.ASSESSMENT_ID 
           AND PTA.PATIENT_ID = PAA.PATIENT_ID 
INNER JOIN 
    dbo.SYS_ASSESSMENT_POINTER AS SAP ON SAP.POINTER_ID = PAA.POINTER_ID 
INNER JOIN 
    dbo.SYS_ASSESSMENT_QUESTION AS SAQ ON SAQ.QUESTION_ID = SAP.QUESTION_ID 
INNER JOIN 
    dbo.SYS_ASSESSMENT_ANSWER AS SAA ON SAA.ANSWER_ID = SAP.ANSWER_ID 
INNER JOIN 
    dbo.PT_BASIC ON PTA.PATIENT_ID = dbo.PT_BASIC.PATIENT_ID 
WHERE 
    (PTA.ASSESSMENT_DATE BETWEEN CONVERT(DATETIME, '2017-09-05 00:00:00', 102) 
          AND CONVERT(DATETIME, '2017-10-12 00:00:00', 102)) 
GROUP BY 
    dbo.PT_BASIC.PATIENT_CODE, dbo.PT_BASIC.NAME_FULL, SAQ.QUESTION_TEXT, 
    SAA.ANSWER_TEXT 
HAVING  
    (SAA.ANSWER_TEXT LIKE '%LEVEL % -%') 

电流输出将与此类似:
2017年9月5日患者ABC正确答案为
2017年9月6日患者ABC ANSWER2
2017年9月7日患者ABC ANSWER3
9 /二千○一十七分之六患者XYZ Answer4

我所期待的是:

2017年9月7日患者ABC ANSWER3
2017年9月6日PA TIENT XYZ回答4

+4

可能出现[检索数据库中每个组的最后一条记录 - SQL Server 2005/2008](https:// stackoverflow.com/questions/4751913/retrieving-last-record-in-each-group-from-database-sql-server-2005-2008) –

+0

交叉应用而不是内部联接。 – xQbert

+1

什么RDBMS和版本?以及PTC_Assessments对答案的分布是什么?每个答案都有很多评估吗?或者只是少数,分布会随着时间而改变? – xQbert

回答

1

如果您的SQL Server版本支持它,则使用ROW_NUMBER() OVER()是从单个表中获得“最新”(或“最早”)行的高效且简单的方法。然而,由于我们对你的数据模型知之甚少,因此猜测如何将行减少到仅仅是可能需要更复杂子查询的“最新答案”并不容易。但是,您仍然可以在该子查询上使用ROW_NUMBER() OVER()。我怀疑问题和答案的本质是表格别名SAP,SAQ,SAA可能都需要参与这个子查询。

请注意,不是直接加入PTA,而是现在是子查询,并且外部查询的连接条件需要RN=1这是具有“最新”日期的行。

SELECT 
     MAX(PTA.ASSESSMENT_DATE) AS Max_Date 
    , SAQ.QUESTION_TEXT 
    , SAA.ANSWER_TEXT 
    , dbo.PT_BASIC.PATIENT_CODE 
    , dbo.PT_BASIC.NAME_FULL 
FROM dbo.PTC_ASSESSMENT_ANSWER AS PAA 
INNER JOIN (
     SELECT 
      * 
      , ROW_NUMBER() OVER (PARTITION BY PATIENT_ID 
           ORDER BY ASSESSMENT_DATE DESC) AS RN 
     FROM dbo.PTC_ASSESSMENT 
     WHERE ASSESSMENT_DATE BETWEEN '20170905' AND '20171012' 
    ) AS PTA ON PTA.ASSESSMENT_ID = PAA.ASSESSMENT_ID 
      AND PTA.PATIENT_ID = PAA.PATIENT_ID 
      AND PTA.RN = 1 
INNER JOIN dbo.SYS_ASSESSMENT_POINTER AS SAP ON SAP.POINTER_ID = PAA.POINTER_ID 
INNER JOIN dbo.SYS_ASSESSMENT_QUESTION AS SAQ ON SAQ.QUESTION_ID = SAP.QUESTION_ID 
INNER JOIN dbo.SYS_ASSESSMENT_ANSWER AS SAA ON SAA.ANSWER_ID = SAP.ANSWER_ID 
INNER JOIN dbo.PT_BASIC ON PTA.PATIENT_ID = dbo.PT_BASIC.PATIENT_ID 
WHERE SAA.ANSWER_TEXT LIKE '%LEVEL % -%' 
GROUP BY 
     dbo.PT_BASIC.PATIENT_CODE 
    , dbo.PT_BASIC.NAME_FULL 
    , SAQ.QUESTION_TEXT 
    , SAA.ANSWER_TEXT 
  1. select distinct(使用GROUP BY任何类似的查询或)
  2. YYYMMDD是在SQL Server中最安全的日期文字不需要在此查询,您不使用样式102
  3. 需要的转换您的条款应该移到where子句,因为它不会评估任何聚合值
0

交叉应用允许您使用相关查询,并按日期desc排序的前n个记录用于每个患者评估。 (审核后,也许你只需要耐心?)

也许只是改变:

INNER JOIN 
    dbo.PTC_ASSESSMENT AS PTA ON PTA.ASSESSMENT_ID = PAA.ASSESSMENT_ID 
           AND PTA.PATIENT_ID = PAA.PATIENT_ID 

TO:

CROSS APPLY (SELECT TOP 1 * 
      FROM dbo.PTC_ASSESSMENT PTA2 
      WHERE PTA2.ASSESSMENT_ID = PAA.ASSESSMENT_ID 
      /*AND PTA2.PATIENT_ID = PAA.PATIENT_ID*/ 
      ORDER BY PTA2.Assessment_date desc) PTA 

给你(我左/ AND PTA2.PATIENT_ID = PAA。 PATIENT_ID/- 我认为你可以省略这个,我把* /留在原地但不需要)

SELECT MAX(PTA.ASSESSMENT_DATE) AS Max_Date 
    , SAQ.QUESTION_TEXT 
    , SAA.ANSWER_TEXT 
    , dbo.PT_BASIC.PATIENT_CODE 
    , dbo.PT_BASIC.NAME_FULL 
FROM dbo.PTC_ASSESSMENT_ANSWER AS PAA 
CROSS APPLY (SELECT TOP 1 * 
      FROM dbo.PTC_ASSESSMENT PTA2 
      WHERE PTA2.ASSESSMENT_ID = PAA.ASSESSMENT_ID --I think you can omit this. 
       /*AND PTA2.PATIENT_ID = PAA.PATIENT_ID*/ 
      ORDER BY PTA2.Assessment_date desc) PTA 
INNER JOIN dbo.SYS_ASSESSMENT_POINTER AS SAP 
    ON SAP.POINTER_ID = PAA.POINTER_ID 
INNER JOIN dbo.SYS_ASSESSMENT_QUESTION AS SAQ 
    ON SAQ.QUESTION_ID = SAP.QUESTION_ID 
INNER JOIN dbo.SYS_ASSESSMENT_ANSWER AS SAA 
    ON SAA.ANSWER_ID = SAP.ANSWER_ID 
INNER JOIN dbo.PT_BASIC 
    ON PTA.PATIENT_ID = dbo.PT_BASIC.PATIENT_ID 
WHERE (PTA.ASSESSMENT_DATE BETWEEN CONVERT(DATETIME, '2017-09-05 00:00:00', 102) AND CONVERT(DATETIME, '2017-10-12 00:00:00', 102)) 
GROUP BY dbo.PT_BASIC.PATIENT_CODE 
     , dbo.PT_BASIC.NAME_FULL 
     , SAQ.QUESTION_TEXT 
     , SAA.ANSWER_TEXT 
HAVING (SAA.ANSWER_TEXT LIKE '%LEVEL % -%') 

看起来你并不担心没有评估的患者,因为你所有的联结都是内在的,或者我们可以使用OUTER APPPLY来确保所有答案保持不变,不管评估是否提供。或者你可以使用row_number()逻辑(Tab Alleman的链接有这个覆盖)和一个cte;但如果交叉应用可用,不妨在这里使用它。

+0

我做了这些改变,现在的结果更好,但如果患者在不同的日子有两个不同的答案,我得到这两个列出。例如:9/6/17 Patient1 Answer1,9/7/17 Patient1 Answer2。当我真正需要的是最新的答案时,我没有得到每个评估答案,只是那些独特的答案。 –

+0

然后消除assessment_ID作为我认为相关查询的一部分。我已将注释块放在部分上,我认为你可以在上面的答案中删除/ * */ – xQbert

+0

我认为离得越近。最大日期字段现在显示最新的评估日期,但我得到了几个不同的答案。对于Patient1,我得到的答案是1,答案2和答案3,但所有3的日期显示最新日期,尽管所有3个答案都是在不同的日子。 –

0

请包括order by PTA.ASSESSMENT_DATE DESC以查看顶部的最新记录。