我有一张包含患者预约列表的表格:他们就诊的诊所以及他们出席的日期。
我正在尝试编写一个给出以下内容的查询:
'在2016年4月至2017年3月期间的任何时间点,哪些患者就诊于'123-45'诊所,以及随后的2例患者(预约日期和就诊人数)?
我试图通过首先查询在该时间范围内参加诊所'123-45'的所有患者的患者ID号列表,然后将此患者ID列表放入WHERE子句中来实现此目的。并使用ROW_NUMBER() OVER (PARTITION BY…
向我提供12个月期间每位患者的所有预约的有序列表。
SELECT
x.Patient_Id
,x.Clinic_Code
,x.Appointment_Date
,x.Row_No FROM
(
SELECT
Patient_Id
,Clinic_Code
,Appointment_Date
,ROW_NUMBER() OVER (PARTITION BY Patient_Id ORDER BY Patient_Id, Appointment_Date asc) [Row_No]
FROM
Appointments
WHERE
Appointment_Date BETWEEN '01/10/2016' AND '30/09/2017'
AND Patient_ID = 'BLO123'
) x
WHERE x.Row_No < 4
然而,这会导致在诊所'123-45'出席之前对任何约会进行编号的意外后果。
所以,如果以下是我的来源:
Patient_ID | Clinic_Code | Appointment_Date
--------------------------------------------
BLO123 | QWE-QW | 01-04-2016
BLO123 | OPD-ZZ | 05-10-2016
BLO123 | 123-45 | 13-11-2016
BLO123 | 333-44 | 15-12-2016
BLO123 | 999-45 | 02-02-2017
BLO123 | 222-44 | 15-02-2017
BLO123 | 777-45 | 19-03-2017
我想要的是:
Patient_ID | Clinic_Code | Appointment_Date | Row_No
--------------------------------------------------------------
BLO123 | 123-45 | 13-11-2016 | 1
BLO123 | 333-44 | 15-12-2016 | 2
BLO123 | 999-45 | 02-02-2017 | 3
但是通过在日期范围内包含前面的约会,我得到了:
Patient_ID | Clinic_Code | Appointment_Date | Row_No
--------------------------------------------------------------
BLO123 | QWE-QW | 01-04-2016 | 1
BLO123 | OPD-ZZ | 05-10-2016 | 2
BLO123 | 123-45 | 13-11-2016 | 3
我想要查询的是忽略在123-45出勤之前的任何诊所预约。 请问有人可以提出是否可以这样做?
答案 0 :(得分:2)
此方法使用common table expression (CTE)查找每位患者在诊所123-45
进行的第一次预约。查询的主体返回所有后续约会。
DECLARE @Appointment TABLE
(
Patient_ID varchar(6),
Clinic_code varchar(6),
Appointment_Date date
)
;
INSERT INTO @Appointment
(
Patient_ID,
Clinic_code,
Appointment_Date
)
VALUES
('BLO123','QWE-QW','20160401'),
('BLO123','OPD-ZZ','20161005'),
('BLO123','123-45','20161113'),
('BLO123','333-44','20161215'),
('BLO123','999-45','20170202')
;
WITH
FirstAppointment AS
(
-- Find patients first vist to clinic 123-45.
SELECT
Patient_ID,
MIN(Appointment_Date) AS FirstAppointment_Date
FROM
@Appointment
WHERE
Appointment_Date >= '20160401'
AND Appointment_Date <= '20170331'
AND Clinic_code = '123-45'
GROUP BY
Patient_ID
)
SELECT
ROW_NUMBER() OVER (PARTITION BY a.Patient_ID ORDER BY a.Appointment_Date) AS Rn,
a.*
FROM
FirstAppointment AS fa
INNER JOIN @Appointment AS a ON a.Patient_ID = fa.Patient_ID
AND a.Appointment_Date >= fa.FirstAppointment_Date
;
答案 1 :(得分:1)
with foo as
(
select
*
from (values
('BLO123','QWE-QW', cast('20160401' as date))
,('BLO123','OPD-ZZ',cast('20161005' as date))
,('BLO123','123-45',cast('20161113' as date))
,('BLO123','333-44',cast('20161215' as date))
,('BLO123','999-45',cast('20170202' as date))
) a(Patient_ID , Clinic_Code , Appointment_Date)
)
,lags as
(
select
*
,lag(Clinic_code,1) over (partition by Patient_id order by Appointment_Date) l1
,lag(Clinic_code,2) over (partition by Patient_id order by Appointment_Date) l2
,ROW_NUMBER() over (partition by Patient_id order by Appointment_Date) rn
from foo
)
select Patient_ID,Clinic_Code,Appointment_Date
,case when Clinic_Code='123-45' then 1
when l1='123-45' then 2
else 3 end Row_Nr
from lags
where '123-45' in (Clinic_Code,l1,l2)
结果:
+----------------------------------------------+
|Patient_ID|Clinic_Code|Appointment_Date|Row_No|
+----------------------------------------------+
|BLO123 |123-45 |2016-11-13 |1 |
|BLO123 |333-44 |2016-12-15 |2 |
|BLO123 |999-45 |2017-02-02 |3 |
+----------------------------------------------+