计算每行之间最近的天数

Calculate closest days count, between each row

给定 table 这样的(dt 列是唯一的):

id | dt          | days_count
------------------------------
1  | 2015-06-01  |  NULL
2  | 2015-06-03  |  NULL
4  | 2015-06-09  |  NULL

我需要计算最近日期之间的间隔天数并更新 days_count 列中的检索结果,并且计算必须从最晚日期开始。也就是说,需要的结果是:

id | dt          | days_count
------------------------------
1  | 2015-06-01  |  NULL
2  | 2015-06-03  |  2
4  | 2015-06-09  |  6

我有 2 个变体:

使用 PL/SQL FOR (SELECT ..) LOOP,获取每一行,按 dt desc 排序并计算当前行日期和上一行日期之间的间隔天数。

这些变体有效,但问题是:也许有更有效的方法?

永远不要在 PL/SQL 中这样做,而在纯 SQL.

您可以简单地使用 LAG() OVER() 分析函数来完成。

例如,

设置

SQL> CREATE TABLE t
  2      (id int, dt date, days_count varchar2(4));

Table created.

SQL>
SQL> INSERT ALL
  2      INTO t (id, dt, days_count)
  3           VALUES (1, to_date('2015-06-01','YYYY-MM-DD'), NULL)
  4      INTO t (id, dt, days_count)
  5           VALUES (2, to_date('2015-06-03','YYYY-MM-DD'), NULL)
  6      INTO t (ID, dt, days_count)
  7           VALUES (4, to_date('2015-06-09','YYYY-MM-DD'), NULL)
  8  SELECT * FROM dual;

3 rows created.

SQL>

查询

SQL> SELECT id, dt, dt - lag(dt) over(order by dt) days_count FROM t;

        ID DT        DAYS_COUNT
---------- --------- ----------
         1 01-JUN-15
         2 03-JUN-15          2
         4 09-JUN-15          6

SQL>

MERGE 语句

SQL> MERGE INTO t
  2      USING(
  3        SELECT id, dt, dt - lag(dt) over(order by dt) days_count FROM t
  4      ) day_interval
  5      ON (t.id = day_interval.id)
  6      WHEN MATCHED THEN UPDATE SET
  7      t.days_count= day_interval.days_count;

3 rows merged.

SQL> SELECT * FROM t;

        ID DT        DAYS
---------- --------- ----
         1 01-JUN-15
         2 03-JUN-15 2
         4 09-JUN-15 6

SQL>