繁体   English   中英

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

[英]Finding the days of the week within a date range using oracle SQL

假设以下表结构:

Event: 
  id: integer
  start_date: datetime
  end_date: datetime

是否可以查询一周中特定日期的所有事件? 例如,我想找到一个查询,该查询将找到每个星期一的事件。 搞清楚如果start_dateend_date是星期一,但我不知道如何找出之间的日期。

首选纯SQL,因为这里存在对存储过程的偏见,而我们从Rails上下文中调用它,据我所知,它也无法处理存储过程。

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访问方法),所以我认为这在效率和可扩展性方面都是最佳方法。

有关更多详细信息,请参见我的博客中的条目:

这应该做得更简单:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM