Unix Technical Forum

SQL - Combine multiple records to give 1 record

This is a discussion on SQL - Combine multiple records to give 1 record within the Oracle Database forums, part of the Database Server Software category; --> I have a table person_id start_month end_month 1 200301 200303 1 200302 200303 1 200303 200304 1 200306 200308 ...


Go Back   Unix Technical Forum > Database Server Software > Oracle Database

Register FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 02-24-2008, 03:58 PM
premgoel@gmail.com
 
Posts: n/a
Default SQL - Combine multiple records to give 1 record



I have a table

person_id start_month end_month
1 200301 200303
1 200302 200303
1 200303 200304
1 200306 200308


For the first 3 records, the end_month of the previous record is less
than the start_month of the next record. I want to write a SQL to
combine them and give me the following result

person_id start_month end_month
1 200301 200304
1 200306 200308

I can easily do it in PL/SQL but wanted to do it in SQL. Please help.

Thanks
PK

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #2 (permalink)  
Old 02-24-2008, 03:58 PM
Rene Nyffenegger
 
Posts: n/a
Default Re: SQL - Combine multiple records to give 1 record

On 2005-08-26, premgoel@gmail.com <premgoel@gmail.com> wrote:
>
>
> I have a table
>
> person_id start_month end_month
> 1 200301 200303
> 1 200302 200303
> 1 200303 200304
> 1 200306 200308
>
>
> For the first 3 records, the end_month of the previous record is less
> than the start_month of the next record. I want to write a SQL to
> combine them and give me the following result
>
> person_id start_month end_month
> 1 200301 200304
> 1 200306 200308



What makes the first 3 records be the first three records?




--
Rene Nyffenegger
http://www.adp-gmbh.ch/
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 02-24-2008, 03:58 PM
premgoel@gmail.com
 
Posts: n/a
Default Re: SQL - Combine multiple records to give 1 record

This is basically to track the period for which the patient was taking
a drug. The patients fills a prescription before the previous one
finishes. So the patient is on the same drug withourt interruption.

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #4 (permalink)  
Old 02-24-2008, 03:58 PM
DA Morgan
 
Posts: n/a
Default Re: SQL - Combine multiple records to give 1 record

premgoel@gmail.com wrote:
> This is basically to track the period for which the patient was taking
> a drug. The patients fills a prescription before the previous one
> finishes. So the patient is on the same drug withourt interruption.


Patients often miss days, often stop taking meds, and often overlap
prescriptions.

It may be your business rules ... but it isn't reality.
--
Daniel A. Morgan
http://www.psoug.org
damorgan@x.washington.edu
(replace x with u to respond)
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #5 (permalink)  
Old 02-24-2008, 03:58 PM
Rene Nyffenegger
 
Posts: n/a
Default Re: SQL - Combine multiple records to give 1 record

On 2005-08-26, premgoel@gmail.com <premgoel@gmail.com> wrote:
> This is basically to track the period for which the patient was taking
> a drug. The patients fills a prescription before the previous one
> finishes. So the patient is on the same drug withourt interruption.


Look into the analytical function lag().

hth
Rene


--
Rene Nyffenegger
http://www.adp-gmbh.ch/
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #6 (permalink)  
Old 02-24-2008, 03:58 PM
ruskie
 
Posts: n/a
Default Re: SQL - Combine multiple records to give 1 record

The following query should provide the required output:

select distinct t1.person_id,
min(t2.start_month) as start_date,
max(t2.end_month) as end_date
from temp t1, temp t2
where t1.start_month <= t2.end_month
and t2.start_month <= t1.end_month
group by t1.person_id, t1.start_month, t1.end_month


RH

premgoel@gmail.com wrote:
> I have a table
>
> person_id start_month end_month
> 1 200301 200303
> 1 200302 200303
> 1 200303 200304
> 1 200306 200308
>
>
> For the first 3 records, the end_month of the previous record is less
> than the start_month of the next record. I want to write a SQL to
> combine them and give me the following result
>
> person_id start_month end_month
> 1 200301 200304
> 1 200306 200308
>
> I can easily do it in PL/SQL but wanted to do it in SQL. Please help.
>
> Thanks
> PK


Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #7 (permalink)  
Old 02-24-2008, 03:58 PM
DA Morgan
 
Posts: n/a
Default Re: SQL - Combine multiple records to give 1 record

ruskie wrote:
> The following query should provide the required output:
>
> select distinct t1.person_id,
> min(t2.start_month) as start_date,
> max(t2.end_month) as end_date
> from temp t1, temp t2
> where t1.start_month <= t2.end_month
> and t2.start_month <= t1.end_month
> group by t1.person_id, t1.start_month, t1.end_month
>
>
> RH


Excuse me but ... SELECT DISTINCT in a GROUP BY?

If a GROUP BY has repeating values they should be dealt
with using GROUP_ID() as in the example at www.psoug.org
click on Morgan's Library
click on GROUP BY
scroll down to "Group By With Repeating Values"

I suspect you will find it far more efficient.

HTH
--
Daniel A. Morgan
http://www.psoug.org
damorgan@x.washington.edu
(replace x with u to respond)
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #8 (permalink)  
Old 02-24-2008, 04:13 PM
Arun Mathur
 
Posts: n/a
Default Re: SQL - Combine multiple records to give 1 record

"select distinct t1.person_id,
min(t2.start_month) as start_date,
max(t2.end_month) as end_date
from temp t1, temp t2
where t1.start_month <= t2.end_month
and t2.start_month <= t1.end_month
group by t1.person_id, t1.start_month, t1.end_month

RH"

This query will give the correct results with the given data. However,
it doesn't take into account that more than two records can combine to
form one. I basically used a hierarchical query to connect the records
based on their start and stop times. From there, I could figure out
the latest month that each record extends to, and then combine them by
returning the earliest month with each maximum latest month.

I'm pasting a SQL*Plus script I wrote to illustrate what I did. It'll
prompt for an html file to spool to. Also note that it drops and
creates a table called person, so as with any script, please do view it
before running. As always, I appreciate any comments/suggestions.

Regards,
Arun


set echo on
set markup html on
set pagesize 0
spool &html_filename_to_output_to
drop table person;
create table person(person_pk number(11) not null,
person_id number(11) not null,
start_month date,
end_month date);
alter table person add constraint person_primary
primary key(person_pk);
--
--
-- insert statements
--
insert into person(person_pk,person_id,start_month,end_month) values
(1,1,to_date('01-JAN-03','DD-MON-YY'),to_date('01-MAR-03','DD-MON-YY'));
insert into person(person_pk,person_id,start_month,end_month) values
(2,1,to_date('01-FEB-03','DD-MON-YY'),to_date('01-MAR-03','DD-MON-YY'));
insert into person(person_pk,person_id,start_month,end_month) values
(3,1,to_date('01-MAR-03','DD-MON-YY'),to_date('01-APR-03','DD-MON-YY'));
insert into person(person_pk,person_id,start_month,end_month) values
(4,1,to_date('01-JUN-03','DD-MON-YY'),to_date('01-AUG-03','DD-MON-YY'));
insert into person(person_pk,person_id,start_month,end_month) values
(5,1,to_date('01-JUL-03','DD-MON-YY'),to_date('01-SEP-03','DD-MON-YY'));
--
insert into person(person_pk,person_id,start_month,end_month) values
(6,1,to_date('01-APR-03','DD-MON-YY'),to_date('01-MAY-03','DD-MON-YY'));
insert into person(person_pk,person_id,start_month,end_month) values
(7,1,to_date('01-FEB-03','DD-MON-YY'),to_date('01-JUN-03','DD-MON-YY'));
--
--

select * from person
order by start_month,end_month;

-- one approach proposed by ruskie
select distinct t1.person_id,
min(t2.start_month) as start_date,
max(t2.end_month) as end_date
from person t1, person t2
where t1.start_month <= t2.end_month
and t2.start_month <= t1.end_month
group by t1.person_id, t1.start_month, t1.end_month;

-- create a view based on a hierarchical query to identify the time
intervals
-- that can extend the other
-- ex. JAN-MAR -> MAR-APR -> APR-MAY
-- JAN-MAR -> FEB-JUN

create or replace view v_schedule_path as
select schedule.*,sys_connect_by_path(t2_person_pk,'/') time_path,
decode(instr(sys_connect_by_path(t2_person_pk,'/'),'/',2),0,
substr(sys_connect_by_path(t2_person_pk,'/'),
instr(sys_connect_by_path(t2_person_pk,'/'),'/',1)+1),
substr(sys_connect_by_path(t2_person_pk,'/'),
instr(sys_connect_by_path(t2_person_pk,'/'),'/',1)+1,
instr(sys_connect_by_path(t2_person_pk,'/'),'/',2)
- instr(sys_connect_by_path(t2_person_pk,'/'),'/',1) -1)) root_branch,
level depth from
(
select t1.person_pk t1_person_pk,t1.person_id
t1_person_id,t1.start_month t1_start_month,t1.end_month t1_end_month,
t2.person_pk t2_person_pk,
t2.person_id t2_person_id,
t2.start_month t2_start_month,
t2.end_month t2_end_month
from person t1,person t2
where t1.person_id = t2.person_id
-- and t2.start_month >= t1.start_month
and t2.start_month <= t1.end_month
and t2.end_month > t1.end_month
) schedule
connect by prior t1_person_pk = t2_person_pk
and t1_person_id = t2_person_id;

select * from v_schedule_path
order by t1_person_id,t1_start_month,t2_end_month;

-- simply identify the end months for each root
create or replace view v_schedule_path2 as
select v_schedule_path.*,person.end_month root_end_month
from v_schedule_path,person
where v_schedule_path.t1_person_id = person.person_id
and v_schedule_path.root_branch = person.person_pk
/
select * from v_schedule_path2
order by t1_person_id,t1_start_month,t1_end_month,root_end_ month
/
-- for each interval, identify the latest ending month it can extend to
create or replace view v_schedule_path3 as
select
t1_person_id,t1_person_pk,t1_start_month,t1_end_mo nth,max(root_end_month)
over (partition by t1_start_month,t1_end_month) max_end_month
from v_schedule_path2;
select * from v_schedule_path3
order by max_end_month,t1_start_month
/
--
-- get the earliest starting month for each latest ending month
--
select t1_person_id,min(t1_start_month) start_month,max_end_month
from v_schedule_path3
group by t1_person_id,max_end_month
order by t1_person_id,min(t1_start_month)
/
select * from v$version;
show user
set markup html off
spool off
quit

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 09:44 AM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com