提取多行连续期间涵盖的日期

Extract days covered in contiguous period over multiple rows

我在 Ingres 10 table 中有如下数据:-

ref, from_date, to_date
A, 01/04/2016, 30/04/2016
A, 30/04/2016, 20/05/2016
A, 25/05/2016, 30/05/2016
B, 01/04/2016, 01/09/2016
B, 01/10/2016, 20/02/2016

to_dates独享。

所以有些线组代表没有间隙的连续周期,它们可以跨越多条线,但有时会有间隙。

我需要计算每个连续期间所涵盖的天数。我想不出办法。

所以对于 ref A,我需要知道第一个连续时间段是 01/04/16 到 20/05/16 这个时间段有 46 天,第二个连续时间段是 25/05 /16 - 2016 年 5 月 30 日。这是 4 天。

我想不出在一个 SQL 语句中执行此操作的巧妙方法。接下来的答案依赖于创建 table 的副本并迭代更新它,直到每个周期都有一个 'earliest continuous from date'。那么这只是为每个ref和from date组合选择最大周期的问题。

在下面的示例中,我 运行 更新了两次,但是对于任意数据,您需要 运行 它直到更新更新 0 行。

另外,我冒昧地修正了日期中的几个拼写错误。

DECLARE GLOBAL TEMPORARY TABLE SESSION.test2 AS
SELECT ref AS ref,
  from_date AS from_date,
  to_date AS to_date,
  from_date AS cont_from
FROM test
ON COMMIT PRESERVE ROWS
WITH NORECOVERY
Executing . . .

(5 rows)
continue
* * SELECT * FROM SESSION.test2
Executing . . .


+------+-------------------------+-------------------------+-------------------------+
|ref   |from_date                |to_date                  |cont_from                |
+------+-------------------------+-------------------------+-------------------------+
|A     |01-apr-2016              |30-apr-2016              |01-apr-2016              |
|A     |30-apr-2016              |20-may-2016              |30-apr-2016              |
|A     |25-may-2016              |30-may-2016              |25-may-2016              |
|B     |01-apr-2016              |01-sep-2016              |01-apr-2016              |
|B     |01-oct-2016              |20-feb-2017              |01-oct-2016              |
+------+-------------------------+-------------------------+-------------------------+
(5 rows)
continue
* * * * * * * * * * *
/* repeat this update until 0 rows are updated */
UPDATE SESSION.test2 b
FROM SESSION.test2 a
SET cont_from = a.cont_from
WHERE b.cont_from <= a.to_date
  AND b.cont_from >  a.from_date
  AND b.ref = a.ref
  AND b.cont_from != a.cont_from;
SELECT * FROM SESSION.test2
Executing . . .

(1 row)

+------+-------------------------+-------------------------+-------------------------+
|ref   |from_date                |to_date                  |cont_from                |
+------+-------------------------+-------------------------+-------------------------+
|A     |01-apr-2016              |30-apr-2016              |01-apr-2016              |
|A     |30-apr-2016              |20-may-2016              |01-apr-2016              |
|A     |25-may-2016              |30-may-2016              |25-may-2016              |
|B     |01-apr-2016              |01-sep-2016              |01-apr-2016              |
|B     |01-oct-2016              |20-feb-2017              |01-oct-2016              |
+------+-------------------------+-------------------------+-------------------------+
(5 rows)
continue
*
/* repeat this update until 0 rows are updated */
UPDATE SESSION.test2 b
FROM SESSION.test2 a
SET cont_from = a.cont_from
WHERE b.cont_from <= a.to_date
  AND b.cont_from >  a.from_date
  AND b.ref = a.ref
  AND b.cont_from != a.cont_from;
SELECT * FROM SESSION.test2
Executing . . .

(0 rows)

+------+-------------------------+-------------------------+-------------------------+
|ref   |from_date                |to_date                  |cont_from                |
+------+-------------------------+-------------------------+-------------------------+
|A     |01-apr-2016              |30-apr-2016              |01-apr-2016              |
|A     |30-apr-2016              |20-may-2016              |01-apr-2016              |
|A     |25-may-2016              |30-may-2016              |25-may-2016              |
|B     |01-apr-2016              |01-sep-2016              |01-apr-2016              |
|B     |01-oct-2016              |20-feb-2017              |01-oct-2016              |
+------+-------------------------+-------------------------+-------------------------+
(5 rows)
continue
* * * * * SELECT ref,cont_from,MAX(to_date - cont_from)
FROM SESSION.test2
GROUP BY ref,cont_from
ORDER BY 1,2
Executing . . .


+------+-------------------------+-------------------------+
|ref   |cont_from                |col3                     |
+------+-------------------------+-------------------------+
|A     |01-apr-2016              |49 days                  |
|A     |25-may-2016              |5 days                   |
|B     |01-apr-2016              |153 days                 |
|B     |01-oct-2016              |142 days                 |
+------+-------------------------+-------------------------+

HTH