如何获取两个日期列之间的日期?

时间:2019-06-17 07:31:49

标签: sql oracle oracle11g

我有两个日期列START_DATE和END_DATE,并且需要获取Oracle中两个日期列之间的日期列表。

START_DATE   | END_DATE
04-JUN-19    | 06-JUN-19
11-AUG-19    | 13-AUG-19

对于sql服务器发现了类似的问题,但无法转换为oracle pl / sql:

Need to get dates between two date columns

尝试过,但未显示出预期的结果。

with dates (dte, edte) as (
      select A.START_DATE, A.END_DATE
      FROM tbl A
      WHERE A.START_DATE <> A.END_DATE
      union all
      select dte + 1, edte
      from dates
      where dte < edte
     )
select dte
from dates;

我想获取列表日期,例如:

2019-06-04
2019-06-05
2019-06-06
2019-08-11
2019-08-12
2019-08-13

但显示:

04-JUN-19
11-AUG-19

5 个答案:

答案 0 :(得分:1)

方法如下:

fin_document:
+-------------------+---------------------------+------+-----+---------+----------------+
| Field             | Type                      | Null | Key | Default | Extra          |
+-------------------+---------------------------+------+-----+---------+----------------+
| id                | int(11)                   | NO   | PRI | NULL    | auto_increment |
| dt_payment        | date                      | YES  |     | NULL    |                
| total_amount      | decimal(10,2)             | NO   |     | 0.00    |                       
+-------------------+---------------------------+------+-----+---------+----------------+

fin_income:
+------------------+---------------+------+-----+-------------------+----------------+
| Field            | Type          | Null | Key | Default           | Extra          |
+------------------+---------------+------+-----+-------------------+----------------+
| id               | int(11)       | NO   | PRI | NULL              | auto_increment |
| document_id      | int(11)       | YES  | MUL | NULL              |                |
| amount           | decimal(10,2) | YES  |     | 0.00              |                
+------------------+---------------+------+-----+-------------------+----------------+

答案 1 :(得分:1)

生成连续整数的一种方法是使用CONNECT BY:

select level n from dual
connect by level <= 3;

N
-
1
2
3

使用Oracle“日期算术”(其中加1意味着增加一天),您可以说:

select date '2019-06-01' + level - 1 dte from dual
connect by level <= 3;

DTE             
----------------
2019-06-01 00:00
2019-06-02 00:00
2019-06-03 00:00

最后,如果您具有版本12c或更高版本,则可以使用LATERAL子句将此逻辑应用于每一行。请注意,WITH子查询不是解决方案的一部分,可以在其中生成输入数据。

with data(START_DATE, END_DATE) as (
  select date '2019-06-04', date '2019-06-06' from dual
  union all
  select date '2019-08-11', date '2019-08-13' from dual
)
select * from data, lateral(
  select start_date + level - 1 dte
  from dual
  connect by start_date + level - 1 <= end_date
);

START_DATE       END_DATE         DTE             
---------------- ---------------- ----------------
2019-06-04 00:00 2019-06-06 00:00 2019-06-04 00:00
2019-06-04 00:00 2019-06-06 00:00 2019-06-05 00:00
2019-06-04 00:00 2019-06-06 00:00 2019-06-06 00:00
2019-08-11 00:00 2019-08-13 00:00 2019-08-11 00:00
2019-08-11 00:00 2019-08-13 00:00 2019-08-12 00:00
2019-08-11 00:00 2019-08-13 00:00 2019-08-13 00:00

最好的问候, 炖阿什顿

P.S。如果您使用的是旧版本,则第一个答案(我刚刚看到的)使用相同的逻辑,除了使用TABLE(CAST(MULTISET ...

答案 2 :(得分:1)

在您的问题中,您尝试了SQL标准的递归子查询分解。要使用该技术,我相信您至少需要版本11.2。

with data(START_DATE, END_DATE) as (
  select date '2019-06-04', date '2019-06-06' from dual
  union all
  select date '2019-08-11', date '2019-08-13' from dual
)
, recurse_dates(start_date, end_date, dte) as (
  select start_date, end_date, start_date from data
  union all
  select start_date, end_date, dte + 1
  from recurse_dates
  where dte < end_date
)
select * from recurse_dates;

START_DATE       END_DATE         DTE             
---------------- ---------------- ----------------
2019-06-04 00:00 2019-06-06 00:00 2019-06-04 00:00
2019-08-11 00:00 2019-08-13 00:00 2019-08-11 00:00
2019-06-04 00:00 2019-06-06 00:00 2019-06-05 00:00
2019-08-11 00:00 2019-08-13 00:00 2019-08-12 00:00
2019-06-04 00:00 2019-06-06 00:00 2019-06-06 00:00
2019-08-11 00:00 2019-08-13 00:00 2019-08-13 00:00

关于, 炖

答案 3 :(得分:0)

通过使用connect by level中的Oracle子句,您可以轻松获得结果:

with t( start_date, end_date ) as
(
 select date'2019-06-04', date'2019-06-06' from dual union all
 select date'2019-06-11', date'2019-06-13' from dual
)
select distinct start_date + level - 1 as "Dates" 
  from t
 connect by level <= end_date - start_date + 1 
    and prior start_date = start_date
    and prior sys_guid() is not null;

Dates
----------
04.06.2019
05.06.2019
06.06.2019
11.06.2019
12.06.2019
13.06.2019

Demo

distinct子句是针对范围之间的重叠日期添加的。

答案 4 :(得分:0)

您的代码可在Oracle 18c上运行:

with dates (dte, edte) as (
      select A.START_DATE, A.END_DATE
      FROM tbl A
      WHERE A.START_DATE <> A.END_DATE
      union all
      select dte + 1, edte
      from dates
      where dte < edte
     )
select dte
from dates;

输出

| DTE       |
| :-------- |
| 04-JUN-19 |
| 11-JUN-19 |
| 05-JUN-19 |
| 12-JUN-19 |
| 06-JUN-19 |
| 13-JUN-19 |

Oracle 18c db <>提琴here

但是,Oracle 11中存在一个错误(编号11840579)(已在11.2.0.3和12.1.0.1中修复),该错误与递归子查询中的日期有关,并且非固定版本的最简单解决方案是添加到日期,但有一个带有非日期列的额外列来处理增量:

WITH dates (dte, edte, step ) AS (
  SELECT A.START_DATE, A.END_DATE, 0
  FROM   tbl A
UNION ALL
  SELECT dte, edte, step + 1
  FROM   dates
  WHERE  dte + step + 1 <= edte
)
SELECT dte + step
FROM   dates;

输出

| DTE+STEP  |
| :-------- |
| 04-JUN-19 |
| 11-JUN-19 |
| 05-JUN-19 |
| 12-JUN-19 |
| 06-JUN-19 |
| 13-JUN-19 |

Oracle 11gR2 db <>提琴here