分层查询调试

时间:2015-05-30 11:33:21

标签: sql sql-server common-table-expression recursive-query

我想要做的是从招生表中我想知道在每个访问日期过去30天内访问过医院两次以上的患者的姓名。我用CTE想出了下面的查询,理想情况下它应该只重新调整两个名字,但它返回3.我不知道我哪里出错了。

create table admissions(Patient_id int, patient_name varchar(50),   visitdate datetime);

insert into admissions (patient_id, patient_name, visitdate) values(1,  'Victor',   cast('2014-04-10 22:01:13.373' as datetime));
insert into admissions (patient_id, patient_name, visitdate) values(1,  'Victor',   cast('2014-06-14 22:01:53.923' as datetime));
insert into admissions (patient_id, patient_name, visitdate) values(1,  'Victor',   cast('2014-04-15 22:01:53.927' as datetime));
insert into admissions (patient_id, patient_name, visitdate) values(1,  'Victor',   cast('2014-04-19 22:01:53.960' as datetime));
insert into admissions (patient_id, patient_name, visitdate) values(1,  'Victor',   cast('2014-04-30 22:01:53.963' as datetime));
insert into admissions (patient_id, patient_name, visitdate) values(2,  'Sam',      cast('2014-04-25 22:04:32.547' as datetime));
insert into admissions (patient_id, patient_name, visitdate) values(2,  'Sam',      cast('2014-04-25 22:04:56.287' as datetime));
insert into admissions (patient_id, patient_name, visitdate) values(2,  'Sam',      cast('2014-06-14 22:04:56.290' as datetime));
insert into admissions (patient_id, patient_name, visitdate) values(2,  'Sam',      cast('2014-09-22 22:04:56.290' as datetime));
insert into admissions (patient_id, patient_name, visitdate) values(2,  'Sam',      cast('2015-04-05 22:04:56.290' as datetime));
insert into admissions (patient_id, patient_name, visitdate) values(3,  'Tony',     cast('2014-04-25 22:45:42.203' as datetime));
insert into admissions (patient_id, patient_name, visitdate) values(3,  'Tony',     cast('2012-10-22 22:45:42.203' as datetime));
insert into admissions (patient_id, patient_name, visitdate) values(3,  'Tony',     cast('2010-05-06 22:45:42.247' as datetime));
insert into admissions (patient_id, patient_name, visitdate) values(3,  'Tony',     cast('2001-08-01 22:45:42.247' as datetime));
insert into admissions (patient_id, patient_name, visitdate) values(3,  'Tony',     cast('2019-05-14 23:07:05.340' as datetime));

--Below query should return only two records only for (Victor and Sam)



with CTE (patient_id, patient_name, visitdate, diff, ranked) as
(
select patient_id, patient_name, visitdate, diff, ranked from
(select 
	patient_id patient_id,
	patient_name patient_name,
	visitdate visitdate, 
	cast(0 as integer) diff,
	rank() over(partition by patient_id order by visitdate desc) ranked
from admissions) a where ranked = 1

union all

select 
	test.patient_id patient_id,
	test.patient_name patient_name,
	test.visitdate visitdate,
	cast((cte.visitdate - test.visitdate)  as integer)diff,
	test.ranked ranked
from (select 
	patient_id patient_id,
	patient_name patient_name,
	visitdate visitdate, 
	rank() over(partition by patient_id order by visitdate desc) ranked
from admissions) test
inner join CTE
	on test.patient_id = CTE.patient_id
	and test.ranked = cte.ranked + 1
where (cte.visitdate - test.visitdate) <=31 
and cte.visitdate <> test.visitdate
)

select * from CTE;
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

没有得到你想要的东西(你说你想要的东西与Sam和Victor不匹配 - Sam的第2行是彼此在30天之内的唯一一行,并且这意味着在另一个之后的30天内只能访问一次)但是试试这个

select distinct
    a.patient_id,
    a.patient_name
from admissions a 
inner join admissions b on 
    a.patient_id = b.patient_id and
    b.visitdate >= (a.visitdate - 30) and 
    b.visitdate < a.visitdate
group by 
    a.patient_id,
    a.patient_name,
    a.visitdate
having
    count(b.visitdate) >= 1

这将使所有在访问后30天内有一次或多次访问的患者(或基本上在30天内访问2次)

如果您想添加更多条件(例如患者最后一次访问后30天内,或2次或更多次等),您应该可以非常轻松地添加其他条件。

SQL小提琴 - http://sqlfiddle.com/#!6/4831e/13