我对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
此处patient
和patientrefts
公共列Pn +代码如果pn +代码组合匹配,那么我们会在patient
表servicecode
查看{{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中实现此任务
答案 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