在SQL查询中选择最新或最近的日期

时间:2017-10-12 19:50:33

标签: sql

我在EHR / EMR数据库中运行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 % -%')

目前的输出与此类似:
9/5/2017患者ABC答案1 9/6/2017患者ABC答案2 9/7/2017患者ABC答案3
9/6/2017患者XYZ答案4

我期待的是:

9/7/2017患者ABC答案3 9/6/2017患者XYZ答案4

3 个答案:

答案 0 :(得分:1)

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

请注意,现在不是直接加入PTA,而是现在是子查询,而外部查询的连接条件需要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 ,即具有“最新”日期的行。

select distinct
    此查询(或使用GROUP BY的任何类似查询)不需要
  1. private boolean cameraFocus(MotionEvent event, @NonNull CameraSource cameraSource, @NonNull String focusMode) { Field[] declaredFields = CameraSource.class.getDeclaredFields(); int pointerId = event.getPointerId(0); int pointerIndex = event.findPointerIndex(pointerId); // Get the pointer's current position float x = event.getX(pointerIndex); float y = event.getY(pointerIndex); float touchMajor = event.getTouchMajor(); float touchMinor = event.getTouchMinor(); Rect touchRect = new Rect((int)(x - touchMajor / 2), (int)(y - touchMinor / 2), (int)(x + touchMajor / 2), (int)(y + touchMinor / 2)); Rect focusArea = new Rect(); focusArea.set(touchRect.left * 2000 / cameraView.getWidth() - 1000, touchRect.top * 2000 / cameraView.getHeight() - 1000, touchRect.right * 2000 / cameraView.getWidth() - 1000, touchRect.bottom * 2000 / cameraView.getHeight() - 1000); // Submit focus area to camera ArrayList<Camera.Area> focusAreas = new ArrayList<Camera.Area>(); focusAreas.add(new Camera.Area(focusArea, 1000)); for (Field field : declaredFields) { if (field.getType() == Camera.class) { field.setAccessible(true); try { camera = (Camera) field.get(cameraSource); if (camera != null) { params = camera.getParameters(); params.setFocusMode(focusMode); params.setFocusAreas(focusAreas); camera.setParameters(params); // Start the autofocus operation camera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean b, Camera camera) { // currently set to auto-focus on single touch } }); return true; } return false; } catch (IllegalAccessException e) { e.printStackTrace(); } break; } } return false; }
  2. yyymmdd是SQL Server中最安全的日期文字,您不需要使用样式102的转换
  3. 您的having子句应移至where子句,因为它不会评估任何聚合值

答案 1 :(得分: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

给你:(我离开/ 和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 % -%')

您似乎并不关心没有评估的患者,因为您的所有联接都在内部,或者我们可以使用外部应用以确保保留所有答案,无论是否已提供评估。

或者你可以使用row_number()逻辑(Tab Alleman的链接覆盖了这个)和cte;但如果交叉申请可用,也可以在这里使用。

答案 2 :(得分:0)

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