【问题标题】:Oracle SQL - how dates are comparedOracle SQL - 如何比较日期
【发布时间】:2015-11-18 06:27:09
【问题描述】:

我是一般的 SQL 新手,尤其是 Oracle。

我创建了一个日期集合 => datesdate (i)

组成

我有一张 table 表格,其中包含 daterevenue 列。

当我查询时

select sum(revenue) from table where date between date(i) and date(i+1)

我无法得到正确的数字 => 值小于正确的数字。

当我制作时

select sum(revenue) from table where date between to_date(date(i),'dd-mm-yyyy') and to_date(date(i+1),'dd-mm-yyyy')

不同的故事 => 我收到空值。

只有

select sum(revenue) from table where date>=date(i) and date<=date(i+1)

效果很好。

但是为什么呢?

【问题讨论】:

  • 默认格式是 yyyy-mm-dd 所以当你转换它时你会得到不同的结果
  • 还有一个问题 - 当我进行查询然后在输出中看到结果时,日期显示为“dd-mm-yyyy”。这很令人困惑。所以,默认处理格式是'yyyy-mm-dd',但默认显示格式可以不同。我说的对吗?
  • @SO ReadytoHelp 谢谢,它帮助了
  • 当你运行select date from table where date&gt;=date(i) and date&lt;=date(i+1) 时,你有什么不同吗? select date from table where date between date(i) and date(i+1)
  • date和集合date的数据类型是什么?

标签: sql oracle date comparison


【解决方案1】:

为什么要将DATE 值转换为DATE 值?

当您执行to_date(date(i),'dd-mm-yyyy') 时,会发生以下情况:

  1. 日期值date(i) 使用当前NLS_DATE_FORMAT 格式隐式转换为字符串。

  2. 然后使用dd-mm-yyyy格式将这个字符串转换回DATE

因此,如果偶然您当前的NLS_DATE_FORMAT 格式等于dd-mm-yyyy,那么您的查询将起作用。

或者,为了使其正常工作,请在运行查询之前执行ALTER SESSION SET NLS_DATE_FORMAT = 'dd-mm-yyyy';。但是,将 DATE 值转换为 DATE 值是一种愚蠢且无用的想法。

【讨论】:

  • 这是正确答案,反对票是不合理的
【解决方案2】:

您集合中的变量已经是日期,而您又将它们转换为日期(这是您永远不应该做的事情)。当您将 DATE 转换为 DATE 时,Oracle 先前使用默认日期格式掩码将该变量转换为字符串。你可以看到你的:

SELECT value
FROM nls_session_parameters
WHERE parameter = 'NLS_DATE_FORMAT'

就我而言,我的日期格式是DD-MM-RR。因此,如果我再次将日期 01-01-2015 转换为日期,它将被转换为:

1. It will be implicitly converted into a string using the DD-MON-RR mask. I would get 01-01-15.
2. Then, it will convert the string 01-01-15 into a date using the mask you provide (dd-mm-yyyy). In this case, to_date('01-01-15','dd-mm-yyyy') will return 01-01-0015.

这可能是您在查询中没有得到任何结果的原因:

select sum(revenue) from table where date between to_date(date(i),'dd-mm-yyyy') and to_date(date(i+1),'dd-mm-yyyy')

如果您改用“dd-mm-rrrr”掩码,它会将字符串 01-01-15 转换为 01-01-2015,并且您的查询可能会返回一些内容。我不知道,这取决于您收藏的日期。

【讨论】:

  • 四位年份yyyy 格式为四位年份格式。 rrrr 也只接受两个值,但情况似乎并非如此。
  • to_date(to_date(..)) 毫无意义。
  • 我只是在解释为什么他的一个查询没有得到任何结果,因为这就是他要问的。当然,这是不必要的。你们在否决之前阅读了我的答案吗?而且我认为这可能与他使用的格式掩码有关。让他决定是不是这样。
  • 你说:“它可能会正常工作”然后重复那个无用的to_date(to_date()) 电话。更改 to_date() 的格式并不能“修复”从日期到 varchar 到日期的错误(隐式)转换(我没有投反对票)
  • to_date(to_date()) 肯定没用。但他正在研究约会是如何运作的,他并没有面临真正的问题。这就是为什么他要进行这种无用的转换,我只是说使用那个面具可能会起作用,因为它对我有用。如果他的隐式掩码有 2 年数字,则 rrrr 掩码可以解决问题。
【解决方案3】:

日期值也包含时间。因此,只有当两个日期包含相同的日期并且时间也相同时,它们才相等。

因此,当您将“17-11-2015 07:15:00”与“17-11-2015”进行比较时,它不会相等。

这将导致返回的行数少于您的语句中的预期:

where date between date(i) and date(i+1)

即使日期相同,日期(加上时间)也可能大于日期(i+1)。

如果您对时间分量不感兴趣,请使用 trunc() 函数来消除时间分量。所以你可以写:

select sum(revenue) from table where trunc(date) between date(i) and date(i+1)

(我认为 date(i) 没有时间)。

【讨论】:

    猜你喜欢
    • 2018-08-31
    • 1970-01-01
    • 2012-04-28
    • 2013-04-04
    • 1970-01-01
    • 1970-01-01
    • 2021-02-14
    • 2017-12-31
    • 2015-12-29
    相关资源
    最近更新 更多