【发布时间】:2017-03-08 04:13:56
【问题描述】:
我有一个包含 LETTER_SENT 日期字段的 Oracle 表。 LETTER_SENT 是一个 varchar2 字段,是一个 yyyymmdd 的文本字符串(所以 20140708 表示这封信是在 2014 年 7 月 8 日发送的)。注意:这不是我的表,我只有对 SELECT 的授权,所以我不能将它强制为 yyyymmdd 日期。
我经常需要查找在某个日期范围内发送的信件。通常,我会在 WHERE IN('开始日期',...,'结束日期')。根据我对 SQL 的了解,这样做不会以任何不会影响索引使用的方式修改字段(而转换为日期或数字然后进行比较会影响索引)。
性能方面,这很好。但是,有时我的日期范围非常大,并且在 WHERE 语句中有一个庞大的 IN、...OR IN、... OR IN 子句就像罪恶一样丑陋。
当日期是索引 varchar2 时,是否还有另一种语法上更漂亮但仍然有效的方法来在 where 子句(date_begin 和 date_end 之间的日期)中进行日期比较?
【问题讨论】:
-
你试过
letter_sent >= '20160101' and letter_sent <= '20160430'吗?我想知道包含此类数字的索引字符串如何提取数据。也许它是高性能的——我不知道。只是好奇你是否尝试过。 -
@zedfoxus 这工作得更好 - 我不敢相信我忘记了这个工作!请将此作为答案发布,以便我可以投票并接受它,我的头说我忘记了这个。
-
Tom Kyte 有一个非常令人信服的会议演示(我曾在 OTN 上的一个线程中看到一个链接) - 他展示了具体示例,说明应该对日期进行编码的
VARCHAR2列上的索引如何表现得非常糟糕与正确的DATE列上的索引相比 - 完全相同的数据(除了该列的不同数据类型)。不要使用VARCHAR2作为日期;这是 100 多个绝佳理由之一。 -
这是一个非常简单的例子。想象一下有两个日期。优化器将尝试生成行数的基数估计。当存储为 VARCHAR2 时。 20170101 - 20161230 是 8871。实际上该值应该是 1。
-
@Joe 我已经添加了我的答案,还包括了其他评论者提供的相同建议 - 使用日期字段而不是 varchar2 以获得长期有效性。