我在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天。
答案 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