【问题标题】:Oracle: Return the specific records based on one column dateOracle:根据一列日期返回特定记录
【发布时间】:2022-09-23 01:04:06
【问题描述】:

我有一个如下的数据库结构。

period month start_date
1 April 2022-04-01
2 May 2022-05-07
3 June 2022-06-04
4 July 2022-07-02
5 August 2022-08-06
6 September 2022-09-03
7 October 2022-10-01
8 November 2022-11-05
9 December 2022-12-03
10 January 2023-01-01
11 February 2023-02-04
12 March 2023-03-04

年度结束日期为 2023 年 3 月 31 日。

基于 current_date,我如何选择查询以返回当前日期在第 6 期间的位置。

我当前的查询如下。

SELECT period FROM table1 as a
WHERE
a.start_date = (SELECT MAX(start_date) FROM table1 as b WHERE 
b.start_date <=current_date) and ROWNUM <= 1

无论如何要改进当前查询以避免使用子查询?

    标签: oracle


    【解决方案1】:

    今天是 9 月 22 日,所以 - 这行吗?

    一些样本数据:

    SQL> with test (period, month, start_date) as
      2    (select  1, 'april'    , date '2022-04-01' from dual union all
      3     select  5, 'august'   , date '2022-08-06' from dual union all
      4     select  6, 'september', date '2022-09-03' from dual union all
      5     select  7, 'october'  , date '2022-10-01' from dual union all
      6     select 10, 'january'  , date '2023-01-01' from dual union all
      7     select 12, 'march'    , date '2023-03-04' from dual
      8    ),
    

    查询从这里开始:

      9  temp as
     10    (select period, month, start_date,
     11       row_number() over (order by start_date desc) rn
     12     from test
     13     where start_date <= sysdate
     14    )
     15  select period
     16  from temp
     17  where rn = 1
     18   /
    
        PERIOD
    ----------
             6
    
    SQL>
    

    仍然使用子查询(或 CTE,如我的示例),但是 - 与您的方法相反,它仅从源表中选择一次,因此应该提高性能。


    更多测试:而不是 sysdate(第 13 行),假设今天是 9 月 2 日(这意味着它在第 5 期):

      9  temp as
     10    (select period, month, start_date,
     11       row_number() over (order by start_date desc) rn
     12     from test
     13     where start_date <= date '2022-09-02'
     14    )
     15  select period
     16  from temp
     17  where rn = 1;
    
        PERIOD
    ----------
             5
    
    SQL>
    

    或者,如果今天是 8 月 7 日:

      9  temp as
     10    (select period, month, start_date,
     11       row_number() over (order by start_date desc) rn
     12     from test
     13     where start_date <= date '2022-08-07'
     14    )
     15  select period
     16  from temp
     17  where rn = 1;
    
        PERIOD
    ----------
             5
    
    SQL>
    

    【讨论】:

      【解决方案2】:

      您对 start_date 的规则似乎是:

      • 如果月份是一月(日历年的第一个月)或四月(通常是财政年度的第一个月),则使用该月的第一天;
      • 否则使用每月的第一个星期六。

      如果是这种情况,那么您可以计算下个月的开始日期并使用查询:

      SELECT *
      FROM   table1
      WHERE  start_date <= SYSDATE
      AND    SYSDATE < CASE
                       WHEN EXTRACT(MONTH FROM ADD_MONTHS(start_date, 1))
                            IN (1, 4) -- 1st month of calendar or financial year
                       THEN TRUNC(ADD_MONTHS(start_date, 1), 'MM')
                       ELSE NEXT_DAY(TRUNC(ADD_MONTHS(start_date, 1), 'MM') - 1, 'SATURDAY')
                       END
      

      然后,对于您的示例数据:

      CREATE TABLE table1 (
        period     NUMBER(2,0),
        month      VARCHAR2(9)
                   GENERATED ALWAYS AS (
                     CAST(
                       TO_CHAR(start_date, 'FXMonth', 'NLS_DATE_LANGUAGE=English')
                       AS VARCHAR2(9)
                     )
                   ),
        start_date DATE
      );
      
      INSERT INTO table1 (period, start_date)
        SELECT LEVEL,
               CASE
               WHEN EXTRACT(MONTH FROM ADD_MONTHS(DATE '2022-04-01', LEVEL - 1))
                    IN (1, 4) -- 1st month of calendar or financial year
               THEN ADD_MONTHS(DATE '2022-04-01', LEVEL - 1)
               ELSE NEXT_DAY(ADD_MONTHS(DATE '2022-04-01', LEVEL - 1) - 1, 'SATURDAY')
               END
        FROM   DUAL
        CONNECT BY LEVEL <= 12;
      

      输出:

      PERIOD MONTH START_DATE
      6 September 2022-09-03 00:00:00

      fiddle

      【讨论】:

      • 如果我的日期 = '2023-04-01',我有一个问题,我不应该得到任何记录。但是当我尝试运行这个查询时,它仍然返回到第 12 期。
      • @Junie 已修复。将'MM' 添加到截断。
      猜你喜欢
      • 1970-01-01
      • 2019-03-29
      • 1970-01-01
      • 1970-01-01
      • 2016-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-06
      相关资源
      最近更新 更多