Brian Baker [MVP]
2003-07-25 22:12:11 UTC
Hello all,
I have a little challenge that I've been struggling with. The scenario is
below. Note that the source table has over 2 million rows. The first
solution we tried copied the table to a temporary table and then used a
cursor to iterate over the rows and delete or modify from the temporary
table as necessary. This worked okay for a small set of the data but the
performance was extremely poor when ran against the whole table.
Thanks for taking a look and please let me know if you need more info!
/*
Scenario:
I have a table that lists enrollment periods for an insurance company.
It is possible for a member to be enrolled in more than one contract on
a given date. I need to create a query on this table that has no
overlapping date periods for a given member_num.
The following are some assumptions / notes:
1. If the enrollment_begin_dt and enrollment_end_dt fall between the
enrollment_begin_dt and enrollment_end_dt of another row for the same
member_num, the row with the earliest enrollment_begin_dt takes
precedence. If both rows have the same enrollment_begin_dt, the row with
the latest enrollment_end_dt takes precedence.
2. If there is an overlap where the dates do not fall in the range then
the earliest enrollment_begin_dt value has to be retained and the latest
enrollment_end_dt value is retained. All other columns in the resulting
row are taken from the source row with the latest enrollment_end_dt.
3. Rows are considered overlapping if the enrollment_end_dt of one record
= the enrollment_begin_dt of the next record.
4. Only overlapping rows should be modified. Rows with contiguous dates
are OK.
5. The actual table has several more columns that will be present in the
query, but they should not have an impact on the date logic used.
Given the sample data below, here is what I need as the results:
member_num contract_num enrollment_begin_dt enrollment_end_dt
---------- ------------ ------------------- -----------------
107272 61927 03/01/1989 12/31/1992
107272 61930 01/01/1993 09/04/1998
107272 61928 9/5/98 12/31/98
107272 61928 1/1/99 6/30/99
107272 61928 7/1/99 12/31/99
107272 61928 1/1/00 10/31/00
257668 120716 10/23/95 12/31/95
257668 120716 1/1/96 5/31/96
257668 120716 6/1/96 12/31/96
257668 120716 1/1/97 12/31/1998
257668 120716 1/1/99 12/31/99
257668 120716 1/1/00 12/31/00
*/
CREATE TABLE [overlap] (
[cdw_id] [bigint] IDENTITY (1, 1) NOT NULL ,
[member_num] [varchar] (25) NULL,
[contract_num] [int] NOT NULL ,
[enrollment_begin_dt] [datetime] NOT NULL ,
[enrollment_end_dt] [datetime] NULL ,
)
INSERT INTO overlap values ('107272', 61930, '3/1/89', '12/31/92')
INSERT INTO overlap values ('107272', 61927, '4/1/90', '12/31/92')
INSERT INTO overlap values ('107272', 61928, '1/1/93', '12/31/93')
INSERT INTO overlap values ('107272', 61930, '1/1/93', '9/4/98')
INSERT INTO overlap values ('107272', 61928, '1/1/94', '12/31/95')
INSERT INTO overlap values ('107272', 61928, '1/1/96', '2/29/96')
INSERT INTO overlap values ('107272', 61928, '3/1/96', '12/31/96')
INSERT INTO overlap values ('107272', 61928, '1/1/97', '9/4/98')
INSERT INTO overlap values ('107272', 61928, '9/5/98', '12/31/98')
INSERT INTO overlap values ('107272', 61928, '1/1/99', '6/30/99')
INSERT INTO overlap values ('107272', 61928, '7/1/99', '12/31/99')
INSERT INTO overlap values ('107272', 61928, '1/1/00', '10/31/00')
INSERT INTO overlap values ('257668', 120716, '10/23/95', '12/31/95')
INSERT INTO overlap values ('257668', 120716, '1/1/96', '5/31/96')
INSERT INTO overlap values ('257668', 120716, '6/1/96', '12/31/96')
INSERT INTO overlap values ('257668', 120716, '1/1/97', '6/16/97')
INSERT INTO overlap values ('257668', 161507, '1/1/97', '6/13/98')
INSERT INTO overlap values ('257668', 120716, '6/17/97', '6/30/97')
INSERT INTO overlap values ('257668', 120716, '7/1/97', '10/31/97')
INSERT INTO overlap values ('257668', 120716, '11/1/97', '12/31/97')
INSERT INTO overlap values ('257668', 120716, '1/1/98', '12/31/98')
INSERT INTO overlap values ('257668', 120716, '1/1/99', '12/31/99')
INSERT INTO overlap values ('257668', 120716, '1/1/00', '12/31/00')
SELECT * FROM overlap
order by member_num, enrollment_begin_dt
DROP TABLE overlap
Brian Baker
I have a little challenge that I've been struggling with. The scenario is
below. Note that the source table has over 2 million rows. The first
solution we tried copied the table to a temporary table and then used a
cursor to iterate over the rows and delete or modify from the temporary
table as necessary. This worked okay for a small set of the data but the
performance was extremely poor when ran against the whole table.
Thanks for taking a look and please let me know if you need more info!
/*
Scenario:
I have a table that lists enrollment periods for an insurance company.
It is possible for a member to be enrolled in more than one contract on
a given date. I need to create a query on this table that has no
overlapping date periods for a given member_num.
The following are some assumptions / notes:
1. If the enrollment_begin_dt and enrollment_end_dt fall between the
enrollment_begin_dt and enrollment_end_dt of another row for the same
member_num, the row with the earliest enrollment_begin_dt takes
precedence. If both rows have the same enrollment_begin_dt, the row with
the latest enrollment_end_dt takes precedence.
2. If there is an overlap where the dates do not fall in the range then
the earliest enrollment_begin_dt value has to be retained and the latest
enrollment_end_dt value is retained. All other columns in the resulting
row are taken from the source row with the latest enrollment_end_dt.
3. Rows are considered overlapping if the enrollment_end_dt of one record
= the enrollment_begin_dt of the next record.
4. Only overlapping rows should be modified. Rows with contiguous dates
are OK.
5. The actual table has several more columns that will be present in the
query, but they should not have an impact on the date logic used.
Given the sample data below, here is what I need as the results:
member_num contract_num enrollment_begin_dt enrollment_end_dt
---------- ------------ ------------------- -----------------
107272 61927 03/01/1989 12/31/1992
107272 61930 01/01/1993 09/04/1998
107272 61928 9/5/98 12/31/98
107272 61928 1/1/99 6/30/99
107272 61928 7/1/99 12/31/99
107272 61928 1/1/00 10/31/00
257668 120716 10/23/95 12/31/95
257668 120716 1/1/96 5/31/96
257668 120716 6/1/96 12/31/96
257668 120716 1/1/97 12/31/1998
257668 120716 1/1/99 12/31/99
257668 120716 1/1/00 12/31/00
*/
CREATE TABLE [overlap] (
[cdw_id] [bigint] IDENTITY (1, 1) NOT NULL ,
[member_num] [varchar] (25) NULL,
[contract_num] [int] NOT NULL ,
[enrollment_begin_dt] [datetime] NOT NULL ,
[enrollment_end_dt] [datetime] NULL ,
)
INSERT INTO overlap values ('107272', 61930, '3/1/89', '12/31/92')
INSERT INTO overlap values ('107272', 61927, '4/1/90', '12/31/92')
INSERT INTO overlap values ('107272', 61928, '1/1/93', '12/31/93')
INSERT INTO overlap values ('107272', 61930, '1/1/93', '9/4/98')
INSERT INTO overlap values ('107272', 61928, '1/1/94', '12/31/95')
INSERT INTO overlap values ('107272', 61928, '1/1/96', '2/29/96')
INSERT INTO overlap values ('107272', 61928, '3/1/96', '12/31/96')
INSERT INTO overlap values ('107272', 61928, '1/1/97', '9/4/98')
INSERT INTO overlap values ('107272', 61928, '9/5/98', '12/31/98')
INSERT INTO overlap values ('107272', 61928, '1/1/99', '6/30/99')
INSERT INTO overlap values ('107272', 61928, '7/1/99', '12/31/99')
INSERT INTO overlap values ('107272', 61928, '1/1/00', '10/31/00')
INSERT INTO overlap values ('257668', 120716, '10/23/95', '12/31/95')
INSERT INTO overlap values ('257668', 120716, '1/1/96', '5/31/96')
INSERT INTO overlap values ('257668', 120716, '6/1/96', '12/31/96')
INSERT INTO overlap values ('257668', 120716, '1/1/97', '6/16/97')
INSERT INTO overlap values ('257668', 161507, '1/1/97', '6/13/98')
INSERT INTO overlap values ('257668', 120716, '6/17/97', '6/30/97')
INSERT INTO overlap values ('257668', 120716, '7/1/97', '10/31/97')
INSERT INTO overlap values ('257668', 120716, '11/1/97', '12/31/97')
INSERT INTO overlap values ('257668', 120716, '1/1/98', '12/31/98')
INSERT INTO overlap values ('257668', 120716, '1/1/99', '12/31/99')
INSERT INTO overlap values ('257668', 120716, '1/1/00', '12/31/00')
SELECT * FROM overlap
order by member_num, enrollment_begin_dt
DROP TABLE overlap
Brian Baker
--
Microsoft MVP -- ASP / ASP.NET
Please post responses to the group
Microsoft MVP -- ASP / ASP.NET
Please post responses to the group