[英]Finding the days of the week within a date range using oracle SQL
假设以下表结构:
Event:
id: integer
start_date: datetime
end_date: datetime
是否可以查询一周中特定日期的所有事件? 例如,我想找到一个查询,该查询将找到每个星期一的事件。 搞清楚如果start_date
或end_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_date
到end_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.