SQL:获取每行的下一个日期值

时间:2017-05-17 07:02:00

标签: sql oracle

我有一个包含日期列的表。

ID  |      Date 
----|-----------
  1 | 2000-01-01
  2 | 2000-02-01
  3 | 2000-02-01
  4 | 2000-03-01

我需要一个为每行返回的选择,ID,日期和表格中所有日期的最小日期(大于当前日期)。

ID  |      Date  |  Next date
----+------------+------------
  1 | 2000-01-01 | 2000-02-01
  2 | 2000-02-01 | 2000-03-01
  3 | 2000-02-01 | 2000-03-01
  4 | 2000-03-01 |     (NULL)

我的第一个方法是

SELECT id, date, LEAD (date, 1) OVER (ORDER BY date NULLS LAST) AS next_date
  FROM t

但这只有在DATE列中的值是唯一的时才有效。

有什么想法吗?

5 个答案:

答案 0 :(得分:6)

您可以使用windowing clause的分析函数。 lead()不支持窗口子句,因此您需要使用类似min()first_value()的句子:

FIRST_VALUE ("Date")
  OVER (ORDER BY "Date" RANGE BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING)

默认的窗口子句为RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW,它会为您的所有行提供2000-01-01的相同值,并且使用ROWS窗口会遇到与您遇到的问题相同的问题{1}}重复日期(ID 2仍会获得lead();如果您使用2000-02-01而不是2000-03-01,则ID 4将获得ROWS BETWEEN CURRENT ROW...而不是null。

使用此范围进行演示:

1 FOLLOWING

仅考虑日期值高于当前行的行。而这仍然只需要一次就能上台。

(我已将with t (ID, "Date") as ( select 1, date '2000-01-01' from dual union all select 2, date '2000-02-01' from dual union all select 3, date '2000-02-01' from dual union all select 4, date '2000-03-01' from dual ) select id, "Date", FIRST_VALUE ("Date") OVER (ORDER BY "Date" RANGE BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING) AS next_date FROM t; ID Date NEXT_DATE ---------- ---------- ---------- 1 2000-01-01 2000-02-01 2 2000-02-01 2000-03-01 3 2000-02-01 2000-03-01 4 2000-03-01 放在双引号中,因为"Date"是一个保留字;从您的示例数据中,它看起来像一个带引号的标识符,但在查询中没有引用,所以它可能只是一个更明智的名字......)

答案 1 :(得分:5)

select * , (select min(t2.date) from table t2 where t2.date > t1.date)
from Table t1

上面的代码在sql server

答案 2 :(得分:2)

回答我自己的问题。 ;-)(只是为那些在这篇文章中磕磕绊绊的人展示另一种选择)

另一种解决方案是使用子选择:

SELECT t.id,
       t.date,
       (SELECT MIN (t.date)
          FROM t t2
         WHERE t2.date > t.date)
          AS next_date
  FROM t;

答案 3 :(得分:1)

一种方法是创建一个包含不同日期及其直接前导值的CTE。然后,将此CTE加入日期的原始表格以获得最终结果。

WITH cte AS (
    SELECT t.date,
           LEAD(t.date, 1) OVER (ORDER BY t.date NULLS LAST) AS next_date
    FROM (SELECT DISTINCT date FROM yourTable) t
)
SELECT
    t1.ID,
    t1.date,
    t2.next_date
FROM yourTable t1
INNER JOIN cte t2
    ON t1.date = t2.date

答案 4 :(得分:1)

这是另一种方法,没有“不同”:

select
  ted.id,
  ted.date_col,
  (select
    min(ted2.date_col)
  from
    test_date_v ted2
  where
    ted2.id != ted.id and
    ted2.date_col > ted.date_col) next_date_col
from
  test_date_v ted;