Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 从一组日期生成日期范围的年份_Sql_Oracle_Date Range - Fatal编程技术网

Sql 从一组日期生成日期范围的年份

Sql 从一组日期生成日期范围的年份,sql,oracle,date-range,Sql,Oracle,Date Range,使用Oracle 12c 我需要从每个ID的一组日期中生成年份的日期范围。我尝试使用LEVEL和CONNECT BY子句,但我不完全理解它,也无法想出解决方案。请参见下面的示例和预期结果。感谢您的帮助 WITH dataset AS (SELECT 1 id,'01-Jan-2015' dt_fr,'01-Jan-2018' dt_to FROM DUAL UNION SELECT 2 id,'01-Dec-2016' dt_fr,'01-Dec-2020' dt_to FRO

使用Oracle 12c

我需要从每个ID的一组日期中生成年份的日期范围。我尝试使用LEVEL和CONNECT BY子句,但我不完全理解它,也无法想出解决方案。请参见下面的示例和预期结果。感谢您的帮助

WITH dataset AS
   (SELECT 1 id,'01-Jan-2015' dt_fr,'01-Jan-2018' dt_to FROM DUAL
      UNION SELECT 2 id,'01-Dec-2016' dt_fr,'01-Dec-2020' dt_to FROM DUAL
      UNION SELECT 3 id,'01-May-2015' dt_fr,'01-May-2015' dt_to FROM DUAL
      )
   SELECT id
      ,--dt_fr
      ,--dt_to
      FROM dataset

ID  yr_from    yr_to
1   01-Jan-15   31-Dec-15
1   01-Jan-16   31-Dec-16
1   01-Jan-17   31-Dec-17
1   01-Jan-18   31-Dec-18
2   01-Dec-16   30-Nov-17
2   01-Dec-17   30-Nov-18
2   01-Dec-18   30-Nov-19
2   01-Dec-19   30-Nov-20
2   01-Dec-20   30-Nov-21
3   01-May-15   30-Apr-16

在Oracle 12中,除了连接依据外,还可以使用crossapply子句为每个输入行分别生成级别。这使得代码更干净,因为您不必处理数据中的循环,而且速度也更快

在代码中,您显示的字符串可能表示日期。我编写查询时,就好像输入是实际日期,输出也是日期一样;我更改了nls_date_格式,以便输出与您的格式匹配,并且我不需要在with子句中的to_date中明确给出格式


令人惊叹的这是我第一次看到克罗斯申请。这是你得到的一些高级查询。谢谢你让它变得简单@JervicBadillo-如果您熟悉通过查询连接生成级别,包括如何使用。。。Previor sys_guid不为null,则不需要交叉应用。然后您将得到一个在较旧版本的Oracle中工作的解决方案。
alter session set nls_date_format = 'dd-Mon-yyyy';

with
  dataset (id, dt_fr, dt_to) as (
    select 1, to_date('01-Jan-2015'), to_date('01-Jan-2018') from dual union all
    select 2, to_date('01-Dec-2016'), to_date('01-Dec-2020') from dual union all
    select 3, to_date('01-May-2015'), to_date('01-May-2015') from dual
  )
select id
     , add_months(dt_fr, 12 * (lvl - 1)) as yr_from
     , add_months(dt_fr, 12 * lvl) - 1   as yr_to
from   dataset
       cross apply
       ( select  level as lvl
         from    dual
         connect by level <= months_between(dt_to, dt_fr) / 12 + 1
       )
order by id, dt_fr   --   if needed
;

 ID YR_FROM     YR_TO      
--- ----------- -----------
  1 01-Jan-2015 31-Dec-2015
  1 01-Jan-2016 31-Dec-2016
  1 01-Jan-2017 31-Dec-2017
  1 01-Jan-2018 31-Dec-2018
  2 01-Dec-2016 30-Nov-2017
  2 01-Dec-2017 30-Nov-2018
  2 01-Dec-2018 30-Nov-2019
  2 01-Dec-2019 30-Nov-2020
  2 01-Dec-2020 30-Nov-2021
  3 01-May-2015 30-Apr-2016