我需要找到定义为的范围的开始和结束日期:开始日期是第一个日期,结束日期是后续日期是结束日期后两个月或更长时间的第一个日期。可能存在多个可能的范围
我的表格结构如下:
ID int identity(1,1),
fk_ID char(9),
dateField datetime
数据如下:
1 a 2012-01-01
2 a 2012-01-05
3 a 2012-01-12
4 b 2012-02-01
5 a 2012-04-01
6 b 2012-05-01
7 a 2012-05-30
预期输出如下:
fk_id startdate enddate
a 2012-01-01 2012-01-12
a 2012-04-01 2012-05-30
b 2012-02-01 2012-02-01
b 2012-05-01 null
编辑: 通过执行以下操作:
CREATE TABLE #temp
(
autonum int identity(1,1),
id char(9),
sd datetime
)
insert into #temp (id, sd) values ('a', '2012-01-01')
insert into #temp (id, sd) values ('a', '2012-01-05')
insert into #temp (id, sd) values ('a', '2012-01-12')
insert into #temp (id, sd) values ('a', '2012-03-01')
insert into #temp (id, sd) values ('a', '2012-04-03')
insert into #temp (id, sd) values ('a', '2012-06-06')
insert into #temp (id, sd) values ('b', '2012-02-12')
insert into #temp (id, sd) values ('b', '2012-02-15')
insert into #temp (id, sd) values ('b', '2012-03-01')
insert into #temp (id, sd) values ('b', '2012-04-03')
insert into #temp (id, sd) values ('b', '2012-06-01')
select t1.id, null as previousend, min(t1.sd) as nextstart
from #temp t1
group by t1.id
union
select t1.id, t1.sd as enddate, (select min(t2.sd) from #temp t2 where t1.id=t2.id and t2.sd>t1.sd) as nextstart
from #temp t1
where (select min(t2.sd) from #temp t2 where t1.id=t2.id and t2.sd>t1.sd) >= dateadd(month, 2, t1.sd)
union
select t1.id, max(t1.sd), null
from #temp t1
group by t1.id
drop table #temp
我可以得到这样的输出:
id previousend nextstart
--------- ----------------------- -----------------------
a NULL 2012-01-01 00:00:00.000
a 2012-04-03 00:00:00.000 2012-06-06 00:00:00.000
a 2012-06-06 00:00:00.000 NULL
b NULL 2012-02-12 00:00:00.000
b 2012-06-01 00:00:00.000 NULL
这是非常接近的,但理想情况下,范围的开始和结束日期将在行上。
答案 0 :(得分:2)
考虑到问题的所有变化,这是我最好的猜测。我仍然发现问题非常混乱,分裂,并且两个案例的预期结果似乎不匹配。有了这个查询:
;WITH x AS
(
SELECT a.id, sd = a.sd, ed = b.sd, rn1 = ROW_NUMBER() OVER
(PARTITION BY a.id, a.sd ORDER BY a.sd)
FROM #temp AS a
LEFT OUTER JOIN #temp AS b
ON a.id = b.id
AND b.sd >= a.sd
AND b.sd <= DATEADD(MONTH, 2, a.sd)
),
y AS
(SELECT id, sd,
ed = (SELECT MAX(ed) FROM x AS x2
WHERE x.id = x2.id AND x2.sd <= DATEADD(MONTH, 2, x.sd)
)
FROM x
WHERE rn1 = 1
),
z AS
(
SELECT id, sd = MIN(sd), ed
FROM y GROUP BY id, ed
)
SELECT id, sd, ed /* = CASE
WHEN ed > sd OR (sd = ed AND NOT EXISTS
(SELECT 1 FROM z AS z2 WHERE z2.id = z.id AND z.sd > z2.sd)) THEN ed END
*/
FROM z
ORDER BY id, sd;
第一组数据的结果:
INSERT #temp (id, sd) VALUES
('a','2012-01-01'),
('a','2012-01-05'),
('a','2012-01-12'),
('b','2012-02-01'),
('a','2012-04-01'),
('b','2012-05-01'),
('a','2012-05-30');
如下:
id sd ed
a 2012-01-01 2012-01-12
a 2012-04-01 2012-05-30
b 2012-02-01 2012-02-01
b 2012-05-01 2012-05-01
第二集:
insert into #temp (id, sd) values ('a', '2012-01-01')
insert into #temp (id, sd) values ('a', '2012-01-05')
insert into #temp (id, sd) values ('a', '2012-01-12')
insert into #temp (id, sd) values ('a', '2012-03-01')
insert into #temp (id, sd) values ('a', '2012-04-03')
insert into #temp (id, sd) values ('a', '2012-06-06')
insert into #temp (id, sd) values ('b', '2012-02-12')
insert into #temp (id, sd) values ('b', '2012-02-15')
insert into #temp (id, sd) values ('b', '2012-03-01')
insert into #temp (id, sd) values ('b', '2012-04-03')
insert into #temp (id, sd) values ('b', '2012-06-01')
如下:
id sd ed
a 2012-01-01 2012-04-03
a 2012-06-06 2012-06-06
b 2012-02-12 2012-06-01
如果取消注释CASE块,您将获得开始日期和结束日期相同的结束日期的NULL。正如我多次提出的那样,你的问题是分裂的,你想要的结果似乎不匹配,所以我不确定答案是正确的。
答案 1 :(得分:1)
尝试在Fiddle上的第二个并且远非优雅,但似乎与最终记录不同,结束日期不是NULL:
CREATE TABLE temp
(
id char(9),
d datetime
);
insert into temp (id, d) values ('a', '2012-01-01');
insert into temp (id, d) values ('a', '2012-01-05');
insert into temp (id, d) values ('a', '2012-01-12');
insert into temp (id, d) values ('a', '2012-04-01');
insert into temp (id, d) values ('a', '2012-05-30');
insert into temp (id, d) values ('b', '2012-02-01');
insert into temp (id, d) values ('b', '2012-05-01');
SELECT
x.id ,
min(x.sd) sd ,
x.ed
FROM
(SELECT
a.id ,
a.sd ,
max(a.ed) ed
FROM
(
SELECT
j.id ,
j.d sd ,
q.D ed
FROM temp j
JOIN temp q
ON
j.id = q.id
AND j.d <= q.d
GROUP BY j.id ,
j.d ,
q.d
) a
WHERE datediff(m,a.sd,a.ed)<=2
GROUP BY a.id ,
a.sd
)x
GROUP BY x.id ,
x.ed
ORDER BY x.id ,
min(x.sd) ,
x.ed