我正在进行查询,我需要查看患者访问诊所时输入的患者生命体征(特别是血压)。我在2015年全年都取得了成绩,当然有一些患者多次访问,我只需要看到最近访问时输入的生命体征。另一个轻微的转折是单独输入收缩压和舒张压,所以我得到的结果如下:
Patient ID Name DOB Test Results Date
---------------------------------------------------------------------------------
1000 John Smith 1/1/1955 BP - Diastolic 120 2/10/2015
1000 John Smith 1/1/1955 BP - Systolic 70 2/10/2015
1000 John Smith 1/1/1955 BP - Diastolic 128 7/12/2015
1000 John Smith 1/1/1955 BP - Systolic 75 7/12/2015
1000 John Smith 1/1/1955 BP - Diastolic 130 10/22/2015
1000 John Smith 1/1/1955 BP - Systolic 76 10/22/2015
9999 Jane Doe 5/4/1970 BP - Diastolic 130 4/2/2015
9999 Jane Doe 5/4/1970 BP - Systolic 60 4/2/2015
9999 Jane Doe 5/4/1970 BP - Diastolic 127 11/20/2015
9999 Jane Doe 5/4/1970 BP - Systolic 65 11/20/2015
有26,000多个结果,所以显然我不想通过每个病人,看看他们最近的结果是什么时候。我希望我的结果看起来像这样:
Patient ID Name DOB Test Results Date
---------------------------------------------------------------------------------
1000 John Smith 1/1/1955 BP - Diastolic 130 10/22/2015
1000 John Smith 1/1/1955 BP - Systolic 76 10/22/2015
9999 Jane Doe 5/4/1970 BP - Diastolic 127 11/20/2015
9999 Jane Doe 5/4/1970 BP - Systolic 65 11/20/2015
我知道出生的名字和出生日期以及不会重复的内容,但我主要关注结果栏。
这是我的疑问:
SELECT DISTINCT
pd.PatientID as [Patient ID],
pd.PatientName as Name,
pd.DateOfBirth as DOB,
v.Test as Test,
v.Results as Results,
v.TestDate as Date
FROM PatientDemographic pd JOIN Vitals v ON pd.PatientID = v.PatientID
WHERE v.TestDate BETWEEN '01/01/2015' AND '12/31/2015'
AND v.Test LIKE 'BP%'
ORDER BY pd.PatientID, v.TestDate
在寻找其他答案后,我尝试为GROUP BY
语句中的MAX()
列执行v.TestDate
和SELECT
聚合函数(我特意引用{ {3}},虽然它适用于Oracle而我使用的是SQL Server,所以我不完全确定语法是否相同)。我的查询看起来像:
SELECT DISTINCT
pd.PatientID as [Patient ID],
pd.PatientName as Name,
pd.DateOfBirth as DOB,
v.Test as Test,
v.Results as Results,
MAX(v.TestDate) as Date
FROM PatientDemographic pd JOIN Vitals v ON pd.PatientID = v.PatientID
WHERE v.TestDate BETWEEN '01/01/2015' AND '12/31/2015'
AND v.Test LIKE 'BP%'
GROUP BY pd.PatientID
不可否认,我使用GROUP BY
时总是有点挣扎。在这种特殊情况下,我得到一个错误,指出我需要将Patient Name列添加到GROUP BY
子句中,所以我这样做,然后它要求DOB。然后测试名称。基本上,它希望我将SELECT
语句中的所有内容添加到GROUP BY
。
进行最近的病人访问的最佳方式是什么?
答案 0 :(得分:4)
一种简单方法使用ROW_NUMBER()
查找每个测试的最新记录:
SELECT pd.PatientID as [Patient ID], pd.PatientName as Name, pd.DateOfBirth as DOB,
v.Test as Test, v.Results as Results, v.TestDate as Date
FROM PatientDemographic pd JOIN
(SELECT v.*,
ROW_NUMBER() OVER (PARTITION BY PatientId, Test ORDER BY TestDate DESC) as seqnum
FROM Vitals v
WHERE v.TestDate BETWEEN '2015-01-01' AND '2015-12-31' AND
v.Test LIKE 'BP%'
) v
ON pd.PatientID = v.PatientID
WHERE seqnum = 1
ORDER BY pd.PatientID, v.TestDate;
答案 1 :(得分:1)
我回避戈登使用的窗口功能。使用子查询的技术也可以完成工作:
Dim Filename
Dim Connection
Dim commandoSQL
Dim Archivo
Dim Nombre
Dim objFSO
Dim outputFile
Call Main
Sub Main
Set objFSO=CreateObject("Scripting.FileSystemObject")
Call startConnection() Set commandoSQL = Connection.Execute("select rest_def.obj_num, hdr_def.line_01, hdr_def.line_02, hdr_def.line_03, hdr_def.line_04, hdr_def.line_05, hdr_def.line_06, trlr_def.line_01, trlr_def.line_02, trlr_def.line_03, trlr_def.line_04, trlr_def.line_05, trlr_def.line_06, trlr_def.line_07, trlr_def.line_08, trlr_def.line_09, trlr_def.line_10, trlr_def.line_11, trlr_def.line_12 from rest_def inner join hdr_def on hdr_def.obj_num rest_def.obj_num inner join trlr_def on trlr_def.obj_num = hdr_def.obj_num where hdr_def.obj_num = 101")
'Archivo = "D:\archives\"
Set Filename = Connection.Execute("Select obj_num FROM rest_def")
Nombre = Filename.getString
Archivo = "D:\archives\" + Nombre + ".txt"
Set outputFile = objFSO.CreateTextFile(Archivo,True)
outputFile.Write commandoSQL & vbCrLf
outputFile.Close
Call closeConnection()
End Sub
Sub startConnection()
Set Connection = WScript.CreateObject("ADODB.Connection")
Connection.Open "DSN=milo; UID=dataBase; PWD=password"
End Sub
Sub closeConnection()
Connection.Close
End Sub
答案 2 :(得分:1)
这适用于MS SQL 2005+
SELECT * FROM (
SELECT row_number() over(partition by pd.PatientID, v.Test order by v.TestDate desc) as rn,
pd.PatientID as [Patient ID],
pd.PatientName as Name,
pd.DateOfBirth as DOB,
v.Test as Test,
v.Results as Results,
v.TestDate as Date
FROM PatientDemographic pd
JOIN Vitals v ON pd.PatientID = v.PatientID
WHERE v.TestDate BETWEEN '01/01/2015' AND '12/31/2015'
AND v.Test LIKE 'BP%') t
WHERE rn = 1
答案 3 :(得分:1)
窗口函数不如NOT EXISTS子句有效。我想提出一个不使用窗口函数的更快的解决方案:
SELECT
pd.PatientID as [Patient ID],
pd.PatientName as Name,
pd.DateOfBirth as DOB,
v.Test as Test,
v.Results as Results,
v.TestDate as Date
FROM PatientDemographic pd JOIN Vitals v ON pd.PatientID = v.PatientID
WHERE
v.TestDate BETWEEN '01/01/2015' AND '12/31/2015'
AND v.Test LIKE 'BP%'
AND NOT EXISTS (
SELECT 1 FROM Vitals as v2 where v2.PatientID = v.PatientID
AND V2.TestDate BETWEEN '01/01/2015' AND '12/31/2015'
AND v2.Test LIKE 'BP%'
AND v2.TestDate > v.TestDate)
答案 4 :(得分:1)
您也可以使用Common Table Expression来实现此目的。
IF OBJECT_ID('tempdb..#RecentPatientVitals') IS NOT NULL
DROP TABLE #RecentPatientVitals;
GO
CREATE TABLE #RecentPatientVitals
(
Patient_ID INT
, Name VARCHAR(100)
, DOB DATE
, Test VARCHAR(150)
, Results INT
, [Date] DATE
);
INSERT INTO #RecentPatientVitals
( Patient_ID, Name, DOB, Test, Results, [Date] )
VALUES ( 1000, 'John Smith', '1/1/1955', 'BP - Diastolic', 120, '2/10/2015' )
, ( 1000, 'John Smith', '1/1/1955', 'BP - Systolic', 70, '2/10/2015' )
, ( 1000, 'John Smith', '1/1/1955', 'BP - Diastolic', 128, '7/12/2015' )
, ( 1000, 'John Smith', '1/1/1955', 'BP - Systolic', 75, '7/12/2015' )
, ( 1000, 'John Smith', '1/1/1955', 'BP - Diastolic', 130, '10/22/2015' )
, ( 1000, 'John Smith', '1/1/1955', 'BP - Systolic', 76, '10/22/2015' )
, ( 9999, 'Jane Doe', '5/4/1970', 'BP - Diastolic', 130, '4/2/2015' )
, ( 9999, 'Jane Doe', '5/4/1970', 'BP - Systolic', 60, '4/2/2015' )
, ( 9999, 'Jane Doe', '5/4/1970', 'BP - Diastolic', 127, '11/20/2015' )
, ( 9999, 'Jane Doe', '5/4/1970', 'BP - Systolic', 65, '11/20/2015' );
SELECT *
FROM #RecentPatientVitals;
WITH PatVitals1
AS ( SELECT Patient_ID
, Name
, DOB
, Test
, MAX(Date) AS Date
FROM #RecentPatientVitals
GROUP BY Patient_ID
, Name
, DOB
, Test
) ,
PatVitals2
AS ( SELECT Patient_ID
, Test
, Results
, Date
FROM #RecentPatientVitals
)
SELECT P1.Patient_ID
, P1.Name
, P1.DOB
, P1.Test
, P2.Results
, P1.Date
FROM PatVitals1 P1
INNER JOIN PatVitals2 P2
ON P2.Patient_ID = P1.Patient_ID
AND P2.Date = P1.Date
AND P2.Test = P1.Test
GROUP BY P1.Patient_ID
, P1.Name
, P1.DOB
, P1.Test
, P2.Results
, P1.Date;