日期计算sql(oracle)

时间:2013-06-24 06:56:54

标签: sql oracle

Row No. Start Date  End Date
1   28/11/2012           28/11/2012
2   28/11/2012            6/12/2012
3   6/12/2012             6/12/2012
4   22/01/2013           23/01/2013
5   23/01/2013  

我根据以上示例数据进行了两次查询: -

  1. SQL将记录带到日期没有连续性的地方(例如,rrecord 3结束 12/12/2012,但记录4于2013年1月22日开始)

  2. 调整日期没有连续性的日期(例如,更新记录的开始日期 4至6/12/12使连续性

  3. 提前致谢 哈利

2 个答案:

答案 0 :(得分:1)

SELECT语句很简单:

select * from your_table t1
where t1.end_date is not null
and not exists
   ( select null from your_table t2
     where t2.start_date = t1.end_date
     and t2.row_no != t1.row_no )

子查询阻止记录3满足自身的限定条件。这可能不是完整的解决方案。如果您有多个具有相同开始日期和结束日期的记录,那么您最终可能无法识别某些记录。在这种情况下,ROW_NO的可靠性很重要。

如果你可以保证对于任何给定的记录对,较高的ROW_NO总是表示按时间顺序排列的记录,那么修复很简单:

     where t2.start_date = t1.end_date
     and t2.row_no > t1.row_no )

在某些情况下,这种担保可能无法实现;这取决于如何分配ROW_NO。但是这里已经有很多假设,除非你提供进一步的细节,否则我不打算解决它们。

UPDATE语句比较棘手。

答案 1 :(得分:1)

您可以使用lag function引用上一行中的值(定义'previous'在查询中的含义;我假设您的'行号'是伪列,而不是您可以订购的实际列,并且您希望它们以开始日期顺序排列):

select start_date, end_date,
  case
    when lag_end_date is null then start_date
    when lag_end_date = start_date then start_date
    else lag_end_date
  end as adj_start_date
from (
  select start_date, end_date,
    lag(end_date) over (order by start_date, end_date) as lag_end_date
  from <your_table>
)

SQL Fiddle)。

when的第一个case子句正在处理“第一”行,其中包含最早的开始日期;由于前一行lag不会是null

然后,您可以过滤结果,以获取start_dateadj_start_date不匹配的结果。 (Another SQL Fiddle)。

您可以在merge中使用相同类型的构造进行更新:

merge into <your table>
using (
  select r_id, start_date, end_date,
    case when lag_end_date is null then null
      when lag_end_date = start_date then null
      else lag_end_date
    end as adj_start_date
  from (
    select rowid as r_id, start_date, end_date,
      lag(end_date) over (order by start_date, end_date) as lag_end_date
    from t42
  )
) t
on (your_table>.rowid = t.r_id and t.adj_start_date is not null)
when matched then
update set <your table>.start_date = t.adj_start_date;

SQL Fiddle)。