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

时间:2009-05-07 20:03:22

标签: sql oracle

假设以下表格结构:

Event: 
  id: integer
  start_date: datetime
  end_date: datetime

有没有办法查询一周中特定日期的所有事件?例如,我想找到一个查询,查找每个星期一的事件。弄清楚start_dateend_date是否属于星期一,但我不知道如何找出它们之间的日期。

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

2 个答案:

答案 0 :(得分:6)

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访问方法),我认为这将是一种最佳方法效率和可扩展性。

请参阅我博客中的条目以获取更多详细信息:

答案 1 :(得分:1)

这应该更简单:

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