sql - 计算下一个日/月组合发生的日期

标签 sql oracle

我有一个月和一天;我正在尝试计算出给定日期之后本月和这一天将存在的下一个日期。

例如,如果我有一个如下表,其中引用日期的格式为'MMDD'。请不要为此责怪我;它是在英国提交申请的官方格式。

create table tmp_ben_dates ( filing_date date, reference_date varchar2(4));
insert all
into tmp_ben_dates values ( to_date('31/12/2011','dd/mm/yyyy'), '1231')
into tmp_ben_dates values ( to_date('31/12/2011','dd/mm/yyyy'), '1130')
into tmp_ben_dates values ( to_date('31/12/2011','dd/mm/yyyy'), '0101')
into tmp_ben_dates values ( to_date('31/07/2011','dd/mm/yyyy'), '0601')
into tmp_ben_dates values ( to_date('31/07/2011','dd/mm/yyyy'), '0801')
select * from dual;

我想返回每个 reference_date 在每个 filing_date 之后出现的第一个日期。例如,在第一个示例中,这将是 31/12/2012,在最后一个示例中,这将是 01/08/2011。

到目前为止,我最好的尝试如下

with new_date as ( 
  select reference_date
       , filing_date
       , add_months( trunc(filing_date,'y')
                   , to_number(substr(reference_date,1,2)) - 1) 
           + to_number(substr(reference_date,3)) - 1 as the_date
    from tmp_ben_dates
         )
select filing_date
     , reference_date
     , case when filing_date < the_date then next_date 
            else add_months(the_date,12) end
  from new_date

返回正确的结果:

FILING_DATE         REFE NEXT_DATE
------------------- ---- -------------------
31/12/2011 00:00:00 1231 31/12/2012 00:00:00
31/12/2011 00:00:00 1130 30/11/2012 00:00:00
31/12/2011 00:00:00 0101 01/01/2012 00:00:00
31/07/2011 00:00:00 0601 01/06/2012 00:00:00
31/07/2011 00:00:00 0801 01/08/2011 00:00:00

然而,这也完全是荒谬的;难以阅读和理解。

也可以使用interval,但我真的不明白它如何让确定正在发生的事情变得不那么困惑。

with new_date as ( 
  select reference_date
       , filing_date
       , trunc(filing_date,'y') 
          + to_yminterval( 'P' 
                           || to_char(to_number(substr(reference_date,1,2)) - 1) 
                           || 'M') 
          + to_dsinterval( 'P' 
                           || to_char(to_number(substr(reference_date,3)) - 1) 
                           || 'D') as the_date
    from tmp_ben_dates
         )
select filing_date
       , reference_date
       , case when filing_date < the_date then the_date 
              else add_months(the_date,12) end as next_date
  from new_date

我在这里遗漏了一些明显的东西吗?在 SQL 中是否有一种简单的方法可以做到这一点?

最佳答案

您可能会发现这更简单。它只是将日期设置为 YYYYMMDD 格式,并将其用作 to_date() 的第二个参数:

with new_date as (
    select reference_date, filing_date,
           to_date(to_char(filing_date, 'yyyy')||reference_date), 'yyyymmdd'
                  ) - 1 as the_date
    from tmp_ben_dates
  )
select filing_date, reference_date,
      (case when filing_date < the_date then next_date
            else add_months(the_date,12)
       end)
from new_date 

关于sql - 计算下一个日/月组合发生的日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11971921/

相关文章:

oracle - 使用 Oracle 字典 View 发现 PL/SQL 包级类型

oracle - 使用Sqoop从Oracle导入到HBase时修改数据

sql - 如何创建两个相互具有外键约束的 SQL 表?

php - 优化大表上的计数 SQL 查询

mysql - 如何不允许在数据库中复制特定值

oracle - PL/SQL 表函数之间的流水线

oracle - oracle数据库中不区分大小写的唯一约束

mysql - 使用 SQL 对团队竞争值求和

sql - 将日期范围转换为行集

python - 重用游标与创建新游标的权衡是什么?