0

这是如何使用查询获取 2 个给定日期之间的月份列表的后续问题? 真的。(我怀疑这是因为我不太了解按级别连接子句背后的逻辑!)

我所拥有的是这样的数据列表

ID | START_DATE  | END_DATE
 1 | 01-JAN-2018 | 20-JAN-2018
 2 | 13-FEB-2018 | 20-MAR-2018
 3 | 01-MAR-2018 | 07-MAR-2018

我想尝试得到的是一个列表,其中包含每个 ID 的开始日期和结束日期之间的所有天数。

因此,例如,我想要一个给出的列表

ID | DATE
 1 | 01-JAN-2018
 1 | 02-JAN-2018
 1 | 03-JAN-2018 
...
 1 | 19-JAN-2018
 1 | 20_JAN-2018
 2 | 13-FEB-2018
 2 | 14-FEB-2018
 2 | 15-FEB-2018 
...

等等

我试图做的是调整上述链接中的一个答案,如下所示

select id
, trunc(start_date+((level-1)),'DD') 
from (
  select id
  , start_date
  , end_date
  from blah
 ) 
connect by level <= ((trunc(end_date,'DD')-trunc(start_date,'DD'))) + 1

这给了我我想要的东西,但随后有一大堆重复的日期,就好像它就像一个笛卡尔连接。我需要添加一些简单的东西来解决这个问题吗?

4

2 回答 2

2

我喜欢递归 CTE:

with cte as (
      select id, start_dte as dte, end_dte
      from blah
      union all
      select id, dte + 1, end_dte
      from cte
      where dte < end_dte
     )
select *
from cte
order by id, dte;

这是 ANSI 标准语法,适用于其他几个数据库。

于 2018-07-04T15:18:53.293 回答
0

您尝试执行的分层查询需要包含id = prior id在 connect-by 子句中,但由于这会导致具有多个源行的循环,您还需要包含对非确定性函数的调用,例如dbms_random.value

select id, start_date + level - 1 as day
from blah
connect by level <= end_date - start_date + 1
and prior id = id
and prior dbms_random.value is not null

使用 CTE 中的示例数据,将返回 63 行:

with blah (ID, START_DATE, END_DATE) as (
            select 1, date '2018-01-01', date '2018-01-20' from dual
  union all select 2, date '2018-02-13', date '2018-03-20' from dual
  union all select 3, date '2018-03-01', date '2018-03-07' from dual
)
select id, start_date + level - 1 as day
from blah
connect by level <= end_date - start_date + 1
and prior id = id
and prior dbms_random.value is not null;

        ID DAY       
---------- ----------
         1 2018-01-01
         1 2018-01-02
         1 2018-01-03
...
         1 2018-01-19
         1 2018-01-20
         2 2018-02-13
         2 2018-02-14
...
         3 2018-03-05
         3 2018-03-06
         3 2018-03-07

您不需要trunc()日期,除非它们有非午夜时间,在这种情况下这似乎不太可能,即使这样,如果只有结束日期有更晚的时间(如 23:59:59),也可能没有必要。

不过,递归 CTE 在很多方面都更直观,至少在您了解了它们的基本概念之后;所以我可能也会使用 Gordon 的方法。性能可能存在差异,它们是否适用于大量数据(或生成的行),但对于大量数据,值得比较不同的方法以找到最合适/性能最好的方法。

于 2018-07-04T16:14:56.033 回答