需要在SQL Server 2008中基于条件查询提供帮助

时间:2015-11-17 17:47:15

标签: sql-server sql-server-2008

我对SQL Server有疑问

表:patient

dos             |pn     |code   |servicecode
--------------------------------------------
2015-09-21      |10     |4      |90
2015-10-06      |10     |4      |91
2015-09-04      |10     |4      |92
2015-04-07      |11     |5      |94
2015-04-08      |11     |5      |94
2015-02-02      |12     |6      |96
2015-02-02      |12     |6      |97
2015-07-21      |12     |6      |94
2012-11-07      |13     |7      |94
2012-11-07      |13     |7      |99
2013-10-07      |13     |7      |90
2014-11-09      |13     |7      |98
2014-12-17      |13     |7      |90

表2:Patientrefs

Pn    |  code    | sdate      |  edate 
------------------------------------------
10    |   4      | 2015-09-04 | 2015-10-05
11    |   5      | 2015-04-01 | 2015-09-21
12    |   6      | 2015-02-02 | 2015-10-12
12    |   6      | 2014-04-20 | 2014-05-23
13    |   7      | 2012-11-05 | 2015-05-20

表3:PatientService

Servicecode
-----------
90
94

此处patientpatientrefts公共列Pn +代码如果pn +代码组合匹配,那么我们会在patientservicecode查看{{patientservice之后查看min(dos) 1}}表服务代码然后该组合匹配然后我们认为dos是minimumdos

根据上面的表格,我想要输出如下

pn    | code   | mindos
---------------------------
11    | 5      | 2015-04-07
13    | 7      | 2012-11-07

这里pn = 10和pn = 12没有mindos,因为min(dos)相关服务代码不满足于患者服务表服务代码

我试过这个

 select
     pn, code, dos as mindos 
 from 
     (select 
          pn, code, servicecode 
      from
          (select    
               pn, code, servicecode,
               row_number() over (partition by pn, code order by dos) as rn
           from patient) a
      inner join   
           patientrefs b on a.pn = b.pn and a.code = b.code and b.rn = 1
                         and a.dos between b.sdate and b.edate) as mindos 
 inner join 
     patientservic c on mindos.servicecode = c.servicecode

但上述查询并未准确返回预期结果。

请告诉我如何编写查询以在SQL Server中实现此任务

1 个答案:

答案 0 :(得分:0)

使用CTE,你可以在范围内执行min(dos)和""检查。然后只需将患者和PatientSevice表加入CTE即可验证代码。下面是重新创建示例数据集的代码和返回最终数据集的查询。享受!

    /* RECREATE THE DATASETS

    IF OBJECT_ID('patient') IS NOT NULL
        DROP TABLE patient

    CREATE TABLE patient
    (
          dos  DATE
        , pn   INT
        , code INT
        , servicecode INT
    )

    INSERT patient
    VALUES ('2015-09-21', 10, 4, 90)
          ,('2015-10-06', 10, 4, 91)
          ,('2015-09-04', 10, 4, 92)
          ,('2015-04-07', 11, 5, 94)
          ,('2015-04-08', 11, 5, 94)
          ,('2015-02-02', 12, 6, 96)
          ,('2015-02-02', 12, 6, 97)
          ,('2015-07-21', 12, 6, 94)
          ,('2012-11-07', 13, 7, 94)
          ,('2012-11-07', 13, 7, 99)
          ,('2013-10-07', 13, 7, 90)
          ,('2014-11-09', 13, 7, 98)
          ,('2014-12-17', 13, 7, 90)

    IF OBJECT_ID('Patientrefs') IS NOT NULL
        DROP TABLE Patientrefs

    CREATE TABLE Patientrefs
    (
          pn   INT
        , code INT
        , sdate DATE
        , edate DATE
    )

    INSERT Patientrefs
    VALUES (10, 4, '2015-09-04', '2015-10-05')
          ,(11, 5, '2015-04-01', '2015-09-21')
          ,(12, 6, '2015-02-02', '2015-10-12')
          ,(12, 6, '2014-04-20', '2014-05-23')
          ,(13, 7, '2012-11-05', '2015-05-20')

    IF OBJECT_ID('PatientService') IS NOT NULL
        DROP TABLE PatientService

    CREATE TABLE PatientService
    (
          servicecode INT
    )

    INSERT PatientService
    VALUES (90),(94)

    */

    WITH CTEmindos AS -->>Get the min(dos)
    (
        SELECT pn, code, MIN(dos) mindos
        FROM patient
        GROUP BY pn, code
    ),
    CTEinrange AS  -->>eliminate min(dos) if it's not in range
    (
        SELECT c.pn, c.code, c.mindos
        FROM Patientrefs cpr
            JOIN CTEmindos c ON c.pn = cpr.pn AND c.code = cpr.code
        WHERE c.mindos BETWEEN cpr.sdate AND cpr.edate
    )
    -->>if the min(dos) is in range return only valid service code records
    SELECT ci.pn, ci.code, ci.mindos
    FROM patient p
        JOIN CTEinrange ci ON ci.pn = p.pn AND ci.code = p.code AND ci.mindos = p.dos
        JOIN PatientService ps ON ps.Servicecode = p.servicecode