提取多行中连续时段内的天数

时间:2016-11-18 16:30:44

标签: sql ingres

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

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是独占的。

因此,一些线条代表连续的时间段没有间隙,这些线条可以跨越多条线,但有时会有间隙。

我需要计算每个连续时期所涵盖的日子。我想不出办法做到这一点。

因此,对于参考A,我需要知道第一个连续时间是01/04/16到20/05/16,并且在此期间有46天,并且第二个连续时期是25/05/16 - 2016年5月30日。这是4天。

1 个答案:

答案 0 :(得分:1)

我无法想到在一个SQL语句中执行此操作的聪明方法。接下来的答案依赖于创建表的副本并迭代更新它,直到我们对每个时段都有一个“最早的连续日期”。然后,这只是为每个参考和日期组合选择最大周期的问题。

在下面的示例中,我运行了两次更新,但是对于任意数据,您需要运行它,直到更新更新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