使用 oracle SQL 查找日期范围内的星期几

Posted

技术标签:

【中文标题】使用 oracle SQL 查找日期范围内的星期几【英文标题】:Finding the days of the week within a date range using oracle SQL 【发布时间】:2009-05-07 20:03:21 【问题描述】:

假设如下表结构:

Event: 
  id: integer
  start_date: datetime
  end_date: datetime

有没有办法查询一周中某一天的所有事件?例如,我想找到一个查询,该查询可以找到星期一的每个事件。确定start_dateend_date 是否在星期一,但我不知道如何找出两者之间的日期。

Pure SQL 是首选,因为这里存在对存储过程的偏见,我们从 Rails 上下文中调用它,据我了解,它也不能处理存储过程。

【问题讨论】:

【参考方案1】:
SELECT  *
FROM    event
WHERE   EXISTS
        (
        SELECT  1
        FROM    dual
        WHERE   MOD(start_date - TO_DATE(1, 'J') + level - 1, 7) = 6
        CONNECT BY
                level <= end_date - start_date + 1
        )

子查询从start_dateend_date 迭代所有天,每天检查,如果是Monday,则返回1

您可以轻松地将此查询扩展为更复杂的条件:检查事件是否落在ANY Monday OR Friday 13th,例如:

SELECT  *
FROM    event
WHERE   EXISTS  (
        SELECT  1
        FROM    dual
        WHERE   MOD(start_date - TO_DATE(1, 'J') + level - 1, 7) = 6
                OR (MOD(start_date - TO_DATE(1, 'J') + level - 1, 7) = 3 AND TO_CHAR(start_date + level - 1, 'DD') = '13')
        CONNECT BY
                level <= end_date - start_date + 1
        )

请注意,我使用MOD(start_date - TO_DATE(1, 'J') + level - 1, 7) 而不是TO_CHAR('D')。这是因为TO_CHAR('D')NLS_TERRITORY 影响,不应用于检查一周中的某一天。

此查询不使用任何索引,并且始终执行全表扫描。但这在这种特定情况下不是问题,因为给定间隔很可能包含Monday

即使间隔是 1 天长,索引也会返回 14% 的值,如果间隔更长,甚至更多。

由于INDEX SCAN 在这种情况下效率低下,并且内部子查询非常快(它使用内存中的FAST DUAL 访问方法),我认为这将是一种最佳方法,无论是效率还是可扩展性.

查看我博客中的条目了解更多详情:

Checking event dates

【讨论】:

【参考方案2】:

这应该更简单:

select *
from event
where 2 between to_number(trim(to_char(start_date,'D')))
            and to_number(trim(to_char(end_date,'D')))
   or (end_date - start_date) > 6

【讨论】:

如果我将 01.01.2003(星期三)作为 START_DATE 并将 01.01.2004(星期四)作为 END_DATE,则此查询不会返回任何内容。在这些日期之间肯定有很多星期一。

以上是关于使用 oracle SQL 查找日期范围内的星期几的主要内容,如果未能解决你的问题,请参考以下文章

使用 Oracle 查找任意日期范围内的行数

Oracle SQL:查找指定日期前 7 天的日期,不包括星期日和其他特定日期

日期范围内的 Oracle sql 内部联接

Oracle查询一段日期内的星期的日期..例如我要查2011-3-18至2011-3-30内所有星期一的日期..应该怎样查询

在sql中怎样获得已知日期是星期几

SQL从日期范围内的同一表中的不同记录中获取多个项目的总和(ORACLE)