【问题标题】:Oracle sql not reading the entire stringOracle sql没有读取整个字符串
【发布时间】:2021-08-22 04:11:26
【问题描述】:

我有一个 oracle sql 查询来获取从 18/05/2021 到“28/05/2021”的日期。

由于某些原因,斜线后面的值没有被读取,因为第 4 个月的值也被输出了。我不知道我错在哪里。如果可以的话,请帮忙,非常感谢您的宝贵时间。

注意:日期已使用 varchar 数据类型存储在数据库中。

 SELECT datadate
 FROM mytable
 WHERE trailerid= '1'  and datattime>'05:00:00' and datattime<'12:00:00'
 AND datadate between '18/05/2021'  and '28/05/2021'
 GROUP BY datadate ORDER BY datadate;

电流输出


DATADATE
----------------
18/05/2021
19/04/2021
19/05/2021
20/05/2021
21/04/2021
21/05/2021
22/04/2021
22/05/2021
23/04/2021
23/05/2021
24/04/2021
24/05/2021
25/04/2021
25/05/2021
26/04/2021
26/05/2021
27/04/2021
27/05/2021
28/04/2021
28/05/2021

【问题讨论】:

  • 这种格式的日期没有顺序,因为要比较日期,您需要先比较年,然后是月,然后是天。这部分在你的字符串中的顺序是不同的
  • 我不知道我错在哪里 - 就在您所说的部分附近:日期已使用 varchar 数据类型存储在数据库中 ——不,不,不,不,不。解决这个根本问题,这个后果就会永远消失
  • 嘿,谢谢,我想尝试这个的原因是我在该列中有大量数据。现在看来我必须重新开始。感谢您的回答
  • 如果您要坚持将日期存储为字符串,至少将它们存储在 yyyy-mm-dd 以便 BETWEEN 工作。您抱怨 BETWEEN '18/05..' AND '28/05..' 返回 04 日期,但是字符串19/04.. 确实介于“M/A”在“L/Y”和“Z/Z”之间,即使 A 不在 Y 和 Z 之间!老实说,添加另一个日期时间类型的列,将数据复制到其中,删除旧列并将新列重命名为旧列,大约需要 5 分钟。此外,奖金,您的新闪亮 DATETIME 列也可以存储数据时间的内容。
  • 将日期存储为字符串也会弄乱优化器统计数据,可能导致错误的执行计划

标签: sql oracle date oracle11g


【解决方案1】:

当人们将日期值存储为字符串时会发生这种情况。

看看这是否有帮助:

 AND to_date(datadate, 'dd/mm/yyyy') between to_date('18/05/2021', 'dd/mm/yyyy')  
                                         and to_date('28/05/2021', 'dd/mm/yyyy')

【讨论】:

  • 嘿,谢谢你的回答,但它显示一个错误:( 它不是一个有效的匹配
  • 正如我所说的那样 - 当人们将值存储为字符串时会发生这种情况。该列中的某些值不遵循该日期格式,Oracle 会引发错误。除了查找和修复无效值之外,您无能为力。一个简单但低效的选择是使用循环并存储(或显示)无效行,以便以后修复它们。
  • 您的意思是要将datadate 也包含在to_date 中吗?我认为这就是你回答的重点。
  • 当然,@mathguy。谢谢你。我应该尽量不要一次做几件事,结果真的很差:(
【解决方案2】:

您不必重新开始,只需将数据移动到日期时间列

ALTER TABLE t ADD x DATE;

UPDATE t SET x = to_date(concat(datadate,datatime), 'dd/mm/yyyyhh24:mi:ss'))
WHERE datadate in (SELECT to_char(to_date('1999-12-31', 'yyyy-mm-dd') + level, 'dd/mm/yyyy') FROM dual CONNECT BY level <= 10000)

WH ERE 子句应生成从 2000 年到大约 2030 年的有效日期列表 - 如果您的日期超出此范围,请相应调整

现在应该能够找到无效日期(它们不是 where 子句的一部分,因此 x 应该保持为空)并手动修复:

SELECT * FROM t WHERE x is null

然后删除您的 datadate 和 datatime cols 并将 x 重命名为 datadatetime

现在像 BETWEEN 这样的查询可以正常工作,如果您只需要日期部分,您可以执行 TRUNC(x)。 (您甚至可以 TRUNC 到其他日期部分,如小时,以减少分钟和秒数,或一年中的一周将日期四舍五入到一周的开始等) 如果您只需要时间,您可以执行x - TRUNC(x),它会给出一个十进制数,例如中午 12 点的 0.5 或下午 6 点的 0.75,或者您可以根据您的需要执行 TOCHAR。做x -TRUNC(x) BETWEEN 9.0/24.0 AND 17.0/24.0 比做字符串比较好

【讨论】:

  • 虽然您的整体方法是合理的,但 oracle 中没有 DATETIME 数据类型。此应用程序的正确数据类型是 DATE (ALTER TABLE t ADD x DATE;)
  • 已更新,谢谢 Ed
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-07
  • 1970-01-01
  • 2021-10-04
  • 2021-01-08
  • 1970-01-01
相关资源
最近更新 更多