【问题标题】:Generate a range of records depending on from-to dates根据起始日期生成一系列记录
【发布时间】:2021-08-01 08:22:03
【问题描述】:

我有一个这样的记录表:

Item From To
A 2018-01-03 2018-03-16
B 2021-05-25 2021-11-10

select 的输出应该是这样的:

Item Month Year
A 01 2018
A 02 2018
A 03 2018
B 05 2021
B 06 2021
B 07 2021
B 08 2021

此外,范围不应超过当前月份。在上面的示例中,我们假设当前日期是 2021-08-01。

我正在尝试做类似于THIS with CONNECT BY LEVEL 的事情,但是一旦我还选择了双旁边的表并尝试对记录进行排序,选择就永远不会完成。我还必须将其他几张桌子加入到选择中,但我认为这不会有什么不同。

非常感谢您的帮助。

【问题讨论】:

    标签: sql oracle date-range


    【解决方案1】:

    它是行生成器,但不是你做的那样;很可能您在我的查询(或他们的替代)中缺少第 11 - 16 行。

    SQL> with test (item, date_from, date_to) as
      2    -- sample data
      3    (select 'A', date '2018-01-03', date '2018-03-16' from dual union all
      4     select 'B', date '2021-05-25', date '2021-11-10' from dual
      5    )
      6  -- query that returns desired result
      7  select item,
      8         extract(month from (add_months(date_from, column_value - 1))) month,
      9         extract(year  from (add_months(date_from, column_value - 1))) year
     10  from test cross join
     11    table(cast(multiset
     12      (select level
     13       from dual
     14       connect by level <=
     15         months_between(trunc(least(sysdate, date_to), 'mm'), trunc(date_from, 'mm')) + 1
     16      ) as sys.odcinumberlist))
     17  order by item, year, month;
    
    ITEM       MONTH       YEAR
    ----- ---------- ----------
    A              1       2018
    A              2       2018
    A              3       2018
    B              5       2021
    B              6       2021
    B              7       2021
    B              8       2021
    
    7 rows selected.
    
    SQL>
    

    【讨论】:

    • 在 Oracle 12c 及更高版本中有一个横向连接,它允许关联数据源而无需额外的包装器
    【解决方案2】:

    递归 CTE 是解决此类问题的标准 SQL 方法。在 Oracle 中,这看起来像:

    with cte(item, fromd, tod) as (
          select item, fromd, tod
          from t
          union all
          select item, add_months(fromd, 1), tod
          from cte
          where add_months(fromd, 1) < last_day(tod)
         )
    select item, extract(year from fromd) as year, extract(month from fromd) as month
    from cte
    order by item, fromd;
    

    Here 是一个 dbfiddle。

    【讨论】:

      猜你喜欢
      • 2021-06-20
      • 1970-01-01
      • 1970-01-01
      • 2021-12-19
      • 1970-01-01
      • 2012-12-15
      • 2022-09-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多