鉴于以下数据:
id | user_id | started | closed | dead
-------------------------------------------------------------------------------------------
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
Run Code Online (Sandbox Code Playgroud)
我需要构建一个满足以下规则的数据集:
user_id
所以我们应该只比较来自相同的记录user_id
暂时,我相信我的数据应该是这样的:
用户 ID | 开始| 结尾 -------------------------------------------------- ---- 238846 | 2015-01-27 15:14:50 | 2015-02-02 14:14:13 259140 | 2015-03-23 14:32:16 | 2015-03-24 15:57:32 242650 | 2015-04-16 16:19:08 | 2015-04-16 16:21:06 242650 | 2015-05-21 13:09:06 | 空值 238846 | 2015-05-15 13:17:31 | 空值
任何人都可以就如何构建满足这些条件的查询提供一些指导吗?
这是指向此问题中提供的数据的 DDL 和 DML 语句的链接。
或者,我们可以跳过规则 #2 和 #4,更简单地声明只应包含相互重叠的记录。更重要的规则是,在给定的集合中,如果有一个关闭日期,那么它就成为集合的结束日期,而不是最大的截止日期。
由于问题不够明确,我想出了四种不同的解决方案。解决方案的不同之处在于:
请注意,这是在 SQL Server 中完成的,而不是 MySQL。除了一些非常小的语法更改之外,它的工作原理应该是相同的。
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');
Run Code Online (Sandbox Code Playgroud)
我相信这是提问者正在寻找的解决方案并且与他的结果相匹配。
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
Run Code Online (Sandbox Code Playgroud)
开始时间按可用的第一个关闭日期计算,然后按最早开始日期计算。
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
Run Code Online (Sandbox Code Playgroud)
开始仅按最早日期计算。
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
Run Code Online (Sandbox Code Playgroud)
开始仅按最早日期计算。
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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2233 次 |
最近记录: |