【问题标题】:Oracle Query - Select row having end_date (may be NULL/EMPTY) greater than sysdateOracle 查询 - 选择 end_date(可能为 NULL/EMPTY)大于 sysdate 的行
【发布时间】:2016-01-14 09:29:14
【问题描述】:

我有 Oracle 表 Demo_t,有列 end_date,它的值可能为 null。我想选择所有end_date 大于当前日期的行。

我在下面写了查询

select * from Demo_t where NVL(End_date,sysdate+3) > sysdate;

毫无疑问,查询给出了预期的结果,但我想确保我没有遗漏任何东西或存在任何其他更好的解决方案。它将帮助我更好地了解 Oracle 数据库。

谢谢,

【问题讨论】:

  • 为什么如果 end_date 为空,你会用 sysdate+3 代替?
  • 避免对数据使用函数来实现过滤;那是“不可分割的”(无法使用索引)。更好地使用“sargable”替代品,例如where ( end_date > sysdate or end_date IS NULL ) 请参阅@kikyalex nb 的回答:因为它涉及 OR 运算符,如果有其他条件需要考虑,您可能需要包含括号

标签: sql oracle


【解决方案1】:

如果End_Date 为空,则将其包含在结果中。那是你要的吗? 如果是这样,你可以这样写

SELECT *
FROM DEMO_T
WHERE END_DATE > SYSDATE OR END_DATE IS NULL;

如果你不想这样,可以试试

SELECT *
FROM DEMO_T
WHERE END_DATE > SYSDATE;

在您的代码中:

NVL(End_date,sysdate+3) 实际上为表中的每一行增加sysdate,如果您可以简单地检查End_Date 是否为空,这不是一个好主意

编辑:正如@Thorsten Kettner 所说,查询中只有一个 sysdate,因此不会为每一行计算它

【讨论】:

  • 每个查询只有一个 SYSDATE,因此只有一个 SYSDATE+3。该值不会按行计算。因此,您的第一个查询与原始查询相同,并且执行计划很可能是相同的。区别在于人们认为哪个查询更具可读性。
【解决方案2】:

您的查询很好。您可以使用它或使用(end_date > sysdate or end_date is null) 明确检查NULL。两者都做同样的事情,虽然有些人更喜欢前者,但其他人更喜欢后者,还有一些人总是使用 DECODE 来检查可空列。使用您认为最易读的内容,并在所有查询中坚持一种方式(或在团队中:使用您的同事使用的内容)。保持一致。

不过,有一种方法可以加快此类查询的速度:使用较高的修复日期而不是 SYSDATE+3,通常类似于 DATE'9999-12-31'。然后在这个表达式上创建一个函数索引。

create index idx_end_date on demo_t ( nvl(end_date, date'9999-12-31') );

匹配查询:

select * from demo_t where nvl(end_date, date'9999-12-31') > sysdate;

由于索引涵盖了所有个日期,它比end_date 上的单纯索引更有可能被使用。这可以极大地加快查询速度。

顺便说一句:请注意SYSDATE 包含时间部分。如果end_date 只包含一个日期,那么您可能希望TRUNC(SYSDATE) 进行比较。

【讨论】:

    【解决方案3】:

    您应该使用trunc 表示日期,否则它会比较时间并可能给出错误的输出。

    select *   
      from Demo_t   
     where trunc(nvl(end_date,sysdate+1)) > trunc(sysdate);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-21
      • 2011-03-09
      • 2022-12-05
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      • 2021-09-27
      • 1970-01-01
      相关资源
      最近更新 更多