T-SQL - 我可以强制ROW_NUMBER()OVER(PARTITION BY ...来自设定点的数字记录吗?

时间:2018-01-22 12:19:14

标签: sql-server sql-server-2008 tsql

我有一张包含患者预约列表的表格:他们就诊的诊所以及他们出席的日期。

我正在尝试编写一个给出以下内容的查询:

'在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出勤之前的任何诊所预约。 请问有人可以提出是否可以这样做?

2 个答案:

答案 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     |
+----------------------------------------------+