2

我需要找到定义为范围的开始和结束日期:开始日期是第一个日期,结束日期是第一个日期,后续日期是结束日期后两个月或更长时间。可以有多个可能的范围

我有一个表结构,如:

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

这非常接近,但理想情况下,该范围的开始日期和结束日期将在行上。

4

2 回答 2

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。正如我多次建议的那样,你的问题是分裂的,你想要的结果似乎不匹配,所以我不确定正确的答案是什么。

于 2012-06-16T19:45:21.773 回答
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
于 2012-06-16T15:32:22.330 回答