How to do a SQL group with date gap
I have the following query:
SELECT patient_id FROM patient_visit where visit_type in ('开发者_Python百科A', 'B', 'C')
group by patient_id having count(*) >= 2
To get a list of all patients that had at least two visits of type 'A', 'B', or 'C'.
The patient_visit table also has a visit_date column which stores the date of the visit. My question: is it possible to modify the above query WITHOUT removing the group by statement to query "all patients with at least two visits AND where any of those two visit had a gap of 60 number of days"?
Thanks!
P.S.: i'm using Oracle, if there's a built-in function, I can use that too.
Any two dates, so the first and last visits would qualify?
SELECT patient_id
FROM patient_visit
where visit_type in ('A', 'B', 'C')
group by patient_id
having count(*) >= 2 AND MAX(visit_date) - MIN(visit_date) >= 60
If you meant consecutive, then
SELECT patient_id
FROM patient_visit
where visit_type in ('A', 'B', 'C')
AND EXISTS (
select *
from patient_visit v
where v.visit_type in ('A', 'B', 'C')
and v.patient_id = patient_visit.patient_id
and v.visit_date >= patient_visit.visit_date + 60)
AND NOT EXISTS (
select *
from patient_visit v2
where v2.visit_type in ('A', 'B', 'C')
and v2.patient_id = patient_visit.patient_id
and v2.visit_date > patient_visit.visit_date
and v2.visit_date < patient_visit.visit_date + 60)
group by patient_id
This is an expensive query, something of the order O(N3). The Oracle LAG version could be faster.
SQL> create table patient_visit (patient_id number(38) not null
2 , visit_type varchar2(1) not null
3 , visit_date date not null);
Table created.
SQL> insert into patient_visit
2 select 1, 'A', date '2010-01-01' from dual
3 union all select 1, 'D', date '2010-01-02' from dual
4 -- ignore, by type
5 union all select 1, 'C', date '2010-01-01' + 60 from dual
6 -- 1 is included
7 union all select 1, 'B', date '2011-01-01' from dual
8 -- don't include 1 more than once
9 union all select 2, 'A', date '2010-01-01' from dual
10 union all select 2, 'B', date '2010-01-02' from dual
11 -- breaks up 60 day gap.
12 union all select 2, 'C', date '2010-01-01' + 60 from dual;
7 rows created.
SQL> commit;
Commit complete.
SQL> select patient_id
2 from (select patient_id
3 , visit_date
4 , lag(visit_date) over (partition by patient_id
5 order by visit_date) prior_visit_date
6 from patient_visit
7 where visit_type in ('A', 'B', 'C'))
8 where visit_date - prior_visit_date >= 60
9 group by patient_id;
PATIENT_ID
----------
1
SQL> spool off
I dont have oracle to test but I think this will work
select patient_id from
(SELECT patient_id, dateField FROM patient_visit where visit_type in ('A','B', 'C')
group by patient_id having count(*) >= 2) as temp
where temp.dateField > '2011-01-01'
精彩评论