En raison du manque de clarté de la question, j'ai trouvé quatre solutions différentes. Les solutions diffèrent sur:
- Que vous soyez en "cascade" selon la réponse de Chris
- Lorsque vous avez une date de clôture, que vous utilisiez la date la plus ancienne pour ce groupe ou la date de début pour l'enregistrement qui est fermé.
Veuillez noter que cela se fait dans SQL Server, pas dans MySQL. À part quelques changements de syntaxe très mineurs, cela devrait fonctionner de la même manière.
Configuration commune et exemples de données pour les quatre méthodes
CREATE TABLE #example
(
id int NOT NULL DEFAULT '0',
borrower_id int NOT NULL,
started datetime NULL DEFAULT NULL,
closed datetime NULL DEFAULT NULL,
dead datetime NULL DEFAULT '0000-00-00 00:00:00'
);
CREATE TABLE #result
(
borrower_id int NOT NULL DEFAULT '0',
started datetime NULL DEFAULT NULL,
ended datetime NULL DEFAULT NULL
);
INSERT INTO #example
(id, borrower_id, started, closed, dead)
VALUES
(7714,238846,'2015-01-27 15:14:50','2015-02-02 14:14:13',NULL),
(7882,238846,'2015-01-28 13:25:58',NULL,'2015-05-15 12:16:07'),
(13190,259140,'2015-03-17 10:11:44',NULL,'2015-03-18 07:31:57'),
(13192,259140,'2015-03-17 10:12:17',NULL,'2015-03-18 11:46:46'),
(13194,259140,'2015-03-17 10:12:53',NULL,'2015-03-18 11:46:36'),
(14020,259140,'2015-03-23 14:32:16','2015-03-24 15:57:32',NULL),
(17124,242650,'2015-04-16 16:19:08','2015-04-16 16:21:06',NULL),
(19690,238846,'2015-05-15 13:17:31',NULL,'2015-05-27 13:56:43'),
(20038,242650,'2015-05-19 15:38:17',NULL,NULL),
(20040,242650,'2015-05-19 15:39:58',NULL,'2015-05-21 12:01:02'),
(20302,242650,'2015-05-21 13:09:06',NULL,NULL),
(20304,242650,'2015-05-21 13:09:54',NULL,NULL),
(20306,242650,'2015-05-21 13:10:19',NULL,NULL),
(20308,242650,'2015-05-21 13:12:20',NULL,NULL),
(21202,238846,'2015-05-29 16:47:29',NULL,NULL),
(21204,238846,'2015-05-29 16:47:56',NULL,NULL),
(21208,238846,'2015-05-29 17:05:15',NULL,NULL),
(21210,238846,'2015-05-29 17:05:55',NULL,NULL),
(21918,242650,'2015-06-04 17:04:29',NULL,'2015-06-12 15:47:23');
1. CASCADING - UTILISATION de la solution CLOSED RECORD
C'est la solution que je crois que le demandeur recherche et correspond à ses résultats.
select *
into #temp1
from #example
while (select count(1) from #temp1)>0
begin
--Grab only one user's records and place into a temp table to work with
declare @curUser int
set @curUser=(select min(borrower_id) from #temp1)
select *
into #temp2
from #temp1 t1
where t1.borrower_id=@curUser
while(select count(1) from #temp2)>0
begin
--Grab earliest start date and use as basis for 15 day window (#2 rule)
--Use the record as basis for rules 3 and 4
declare @minTime datetime
set @minTime=(select min(started) from #temp2)
declare @maxTime datetime
set @maxTime=@minTime
declare @curId int
set @curId=(select min(id) from #temp2 where started=@minTime)
select *
into #temp3
from #temp2 t2
where t2.id=@curId
--Remove earliest record from pool of potential records to check rules against
delete
from #temp2
where id=@curId
--Insert all records within 15 days of start date, then remove record from pool
while (select count(1)
from #temp2 t2
where t2.started<=DATEADD(day,15,@maxTime)
or t2.closed<=DATEADD(day,15,@maxTime)
or t2.dead<=DATEADD(day,15,@maxTime) )>0
begin
insert into #temp3
select *
from #temp2 t2
where t2.started<=DATEADD(day,15,@maxTime) or t2.closed<=DATEADD(day,15,@maxTime) or t2.dead<=DATEADD(day,15,@maxTime)
delete
from #temp2
where started<=DATEADD(day,15,@maxTime) or closed<=DATEADD(day,15,@maxTime) or dead<=DATEADD(day,15,@maxTime)
--set new max time from any column
if (select max(started) from #temp3)>@maxTime
set @maxTime=(select max(started) from #temp3)
if (select max(closed) from #temp3)>@maxTime
set @maxTime=(select max(started) from #temp3)
if (select max(dead) from #temp3)>@maxTime
set @maxTime=(select max(started) from #temp3)
end
--Calculate end time according to rule #3
declare @end datetime
set @end = null
set @end=(select min(closed) from #temp3)
if @end is not null
begin
set @minTime=(select started from #temp3 where closed=@end)
end
if @end is null
begin
if(select count(1) from #temp3 where dead is null)=0
set @end= (select max(dead) from #temp3)
end
insert into #result (borrower_id,started,ended)
values (@curUser,@minTime,@end)
drop table #temp3
end
--Done with the one user, remove him from temp table and iterate thru to the next user
delete
from #temp1
where borrower_id=@curUser
drop table #temp2
end
drop table #temp1
drop table #example
select * from #result order by started
drop table #result
2. NON CASCADING - UTILISATION DE LA SOLUTION D'ENREGISTREMENT FERMÉ
Début calculé par la première date de clôture lorsqu'elle est disponible, puis par la première date de début.
select *
into #temp1
from #example
while (select count(1) from #temp1)>0
begin
--Grab only one user's records and place into a temp table to work with
declare @curUser int
set @curUser=(select min(borrower_id) from #temp1)
select *
into #temp2
from #temp1 t1
where t1.borrower_id=@curUser
while(select count(1) from #temp2)>0
begin
--Grab earliest start date and use as basis for 15 day window (#2 rule)
--Use the record as basis for rules 3 and 4
declare @minTime datetime
set @minTime=(select min(started) from #temp2)
declare @curId int
set @curId=(select min(id) from #temp2 where started=@minTime)
select *
into #temp3
from #temp2 t2
where t2.id=@curId
--Remove earliest record from pool of potential records to check rules against
delete
from #temp2
where id=@curId
--Insert all records within 15 days of start date, then remove record from pool
insert into #temp3
select *
from #temp2 t2
where t2.started<=DATEADD(day,15,@minTime)
delete
from #temp2
where started<=DATEADD(day,15,@minTime)
--Insert all records within 15 days of closed, then remove record from pool
insert into #temp3
select *
from #temp2 t2
where t2.closed<=DATEADD(day,15,@minTime)
delete
from #temp2
where closed<=DATEADD(day,15,@minTime)
--Insert all records within 15 days of dead, then remove record from pool
insert into #temp3
select *
from #temp2 t2
where t2.dead<=DATEADD(day,15,@minTime)
delete
from #temp2
where dead<=DATEADD(day,15,@minTime)
--Calculate end time according to rule #3
declare @end datetime
set @end = null
set @end=(select min(closed) from #temp3)
if @end is not null
begin
set @minTime=(select started from #temp3 where closed=@end)
end
if @end is null
begin
if(select count(1) from #temp3 where dead is null)=0
set @end= (select max(dead) from #temp3)
end
insert into #result (borrower_id,started,ended)
values (@curUser,@minTime,@end)
drop table #temp3
end
--Done with the one user, remove him from temp table and iterate thru to the next user
delete
from #temp1
where borrower_id=@curUser
drop table #temp2
end
drop table #temp1
drop table #example
select * from #result
drop table #result
3. NON CASCADING - UTILISATION DE LA SOLUTION DATE LA PLUS TÔT
Début calculé uniquement au plus tôt.
select *
into #temp1
from #example
while (select count(1) from #temp1)>0
begin
--Grab only one user's records and place into a temp table to work with
declare @curUser int
set @curUser=(select min(borrower_id) from #temp1)
select *
into #temp2
from #temp1 t1
where t1.borrower_id=@curUser
while(select count(1) from #temp2)>0
begin
--Grab earliest start date and use as basis for 15 day window (#2 rule)
--Use the record as basis for rules 3 and 4
declare @minTime datetime
set @minTime=(select min(started) from #temp2)
declare @curId int
set @curId=(select min(id) from #temp2 where started=@minTime)
select *
into #temp3
from #temp2 t2
where t2.id=@curId
--Remove earliest record from pool of potential records to check rules against
delete
from #temp2
where id=@curId
--Insert all records within 15 days of start date, then remove record from pool
insert into #temp3
select *
from #temp2 t2
where t2.started<=DATEADD(day,15,@minTime) or t2.closed<=DATEADD(day,15,@minTime) or t2.dead<=DATEADD(day,15,@minTime)
delete
from #temp2
where started<=DATEADD(day,15,@minTime) or closed<=DATEADD(day,15,@minTime) or dead<=DATEADD(day,15,@minTime)
--Calculate end time according to rule #3
declare @end datetime
set @end = null
set @end=(select min(closed) from #temp3)
if @end is null
begin
if(select count(1) from #temp3 where dead is null)=0
set @end= (select max(dead) from #temp3)
end
insert into #result (borrower_id,started,ended)
values (@curUser,@minTime,@end)
drop table #temp3
end
--Done with the one user, remove him from temp table and itterate thru to the next user
delete
from #temp1
where borrower_id=@curUser
drop table #temp2
end
drop table #temp1
drop table #example
select * from #result
drop table #result
4. CASCADING - UTILISATION de la solution DATE LA PLUS TÔT
Début calculé uniquement au plus tôt.
select *
into #temp1
from #example
while (select count(1) from #temp1)>0
begin
--Grab only one user's records and place into a temp table to work with
declare @curUser int
set @curUser=(select min(borrower_id) from #temp1)
select *
into #temp2
from #temp1 t1
where t1.borrower_id=@curUser
while(select count(1) from #temp2)>0
begin
--Grab earliest start date and use as basis for 15 day window (#2 rule)
--Use the record as basis for rules 3 and 4
declare @minTime datetime
set @minTime=(select min(started) from #temp2)
declare @maxTime datetime
set @maxTime=@minTime
declare @curId int
set @curId=(select min(id) from #temp2 where started=@minTime)
select *
into #temp3
from #temp2 t2
where t2.id=@curId
--Remove earliest record from pool of potential records to check rules against
delete
from #temp2
where id=@curId
--Insert all records within 15 days of start date, then remove record from pool
while (select count(1)
from #temp2 t2
where t2.started<=DATEADD(day,15,@maxTime)
or t2.closed<=DATEADD(day,15,@maxTime)
or t2.dead<=DATEADD(day,15,@maxTime) )>0
begin
insert into #temp3
select *
from #temp2 t2
where t2.started<=DATEADD(day,15,@maxTime) or t2.closed<=DATEADD(day,15,@maxTime) or t2.dead<=DATEADD(day,15,@maxTime)
delete
from #temp2
where started<=DATEADD(day,15,@maxTime) or closed<=DATEADD(day,15,@maxTime) or dead<=DATEADD(day,15,@maxTime)
--set new max time from any column
if (select max(started) from #temp3)>@maxTime
set @maxTime=(select max(started) from #temp3)
if (select max(closed) from #temp3)>@maxTime
set @maxTime=(select max(started) from #temp3)
if (select max(dead) from #temp3)>@maxTime
set @maxTime=(select max(started) from #temp3)
end
--Calculate end time according to rule #3
declare @end datetime
set @end = null
set @end=(select min(closed) from #temp3)
if @end is null
begin
if(select count(1) from #temp3 where dead is null)=0
set @end= (select max(dead) from #temp3)
end
insert into #result (borrower_id,started,ended)
values (@curUser,@minTime,@end)
drop table #temp3
end
--Done with the one user, remove him from temp table and iterate thru to the next user
delete
from #temp1
where borrower_id=@curUser
drop table #temp2
end
drop table #temp1
drop table #example
select * from #result order by started
drop table #result