【发布时间】:2017-11-13 21:42:28
【问题描述】:
每当我重新排列 where 子句的条件时,我都会看到不同的查询结果;我试图弄清楚为什么会这样。我被要求尝试弄清楚发生了什么,因此我可以使用一些帮助来确定可能导致问题的原因。需要明确的是,我们在运行 select 语句时没有收到错误,而是收到了意外的数据结果。这是一个 Oracle 数据库(我相信是 10-g)。对于同一个字段,我们有两个条件。首先是确保结果大于 30 年前(这个数据库不是我自己设置的,但是拥有该应用程序的团队决定将 created_date 更改为过去的 30 是个好主意).... .第二个是更具体的日期范围,即 9 月 1 日至 10 月 1 日。
SELECT created_date
FROM tableName
WHERE
created_date > sysdate - 11000 -- 30 years in the past
AND short_name like 'FOO%'
AND trunc(created_date) BETWEEN TO_DATE('09-01-2017', 'MM-DD-YYYY')
AND TO_DATE('10-01-2017', 'MM-DD-YYYY')
在运行上述查询时,我们会在 where 子句末尾收到带有 created_date 的结果。
但是,当我将 created_date 和 sysdate 之间的比较放在两个日期之间的比较之后时,我们会收到正确的结果。
SELECT created_date
FROM tableName
WHERE
short_name like 'FOO%'
AND trunc(created_date) BETWEEN TO_DATE('09-01-2017', 'MM-DD-YYYY')
AND TO_DATE('10-01-2017', 'MM-DD-YYYY')
AND created_date > sysdate - 11000 -- 30 years in the past
此外,我将“AND trunc(created_date) BETWEEN TO_DATE('09-01-2017', 'MM-DD-YYYY')”的 trunc 部分删除为“AND created_date BETWEEN TO_DATE('09-01-2017 ', 'MM-DD-YYYY')" 并在之前或之后通过 sysdate 比较收到预期结果。
SELECT created_date
FROM tableName
WHERE
created_date > sysdate - 11000 -- 30 years in the past
AND short_name like 'FOO%'
AND created_date BETWEEN TO_DATE('09-01-2017', 'MM-DD-YYYY')
AND TO_DATE('10-01-2017', 'MM-DD-YYYY')
编辑:
-
数据库中有许多记录。只有 1 个结果的 created_date 为 22-Sep-17。
SELECT created_date FROM tableName WHERE created_date > sysdate - 11000 -- 30 years in the past AND short_name like 'FOO%' AND trunc(created_date) BETWEEN TO_DATE('09-01-2017', 'MM-DD-YYYY') AND TO_DATE('10-01-2017', 'MM-DD-YYYY')
生成 25 个条目,created_date 为 2004 年 2 月 17 日,1 个条目为 2017 年 9 月 22 日。
- 我理解 sysdate - 11,000 是 30 年多一点。目前的要求是检查 11000 天而不是 30 年。我在年度估计中偏离了。使用 sysdate 是因为被认为是旧的或更新的记录将被放置在比 sysdate - 11000 更远的 created_date 中。我知道当此查询中已经存在另一个日期范围条件时,这没有任何意义,但解决方案已经构建并且送走了。为了做出改变,我需要弄清楚为什么我会得到我得到的,这就是我在这里发帖的原因。
- 第二个日期范围(在本例中为 09-01-2017 和 10-01-2017)是传入的参数,因此它们可以是从过去任何一天到今天的任何范围。我知道这是一个糟糕的设计,但我没有构建它。
这些将为之间的值提供两个微妙不同的结果 2017-10-01 00:00:01 和 2017-10-01 23:59:59。使用 TRUNC 的查询 将包括没有 TRUNC 的范围 排除在外。
预期结果是在 17 年 9 月 22 日的日期范围内返回记录;但是,我们收到了 25 条记录,所有记录的日期均为 2004 年 2 月 17 日......如果我删除 created_date > sysdate - 11000,我也会收到唯一的一条记录。
【问题讨论】:
-
你能举一个不符合你条件的日期例子吗?也许在选择时添加 to_char(created_date,'MM-DD-YYYY') 以便我们知道格式?为什么您需要在两者之间进行 trunc(Created_Date) 呢?好的,我知道为什么如果 create_Date 是 '10-01-2017 13:50' 或其他东西,你会想要它.. 只会伤害索引的使用。
-
我们看到很多问题,例如“为什么 Oracle 要做这件奇怪的事情?”标准答案是甲骨文没有做那件奇怪的事,只是你不完全了解甲骨文在做什么。因此,请发布一个可重现的测试用例,其中包含演示此行为的示例数据。
-
知道您的数据库版本:
select * from v$version,并请提供示例数据来证明您遇到的问题。 -
如果你想减去 30 年,那么不要减去天,而是减去年:
sysdate - interval '30' year -
30 年不是问题,但返回的日期是 2004 年和 2017 年,这表明在 09-01-2017 和 10-1-2017 之间的第二个日期范围正在忽略。