比较两个日期Oracle的多案例

Posted

技术标签:

【中文标题】比较两个日期Oracle的多案例【英文标题】:Multi case when for compare two dates Oracle 【发布时间】:2021-06-30 16:50:07 【问题描述】:

我有一个 sql 查询,它使用“case when”来比较两个日期然后赋值,我的代码有效,但我想知道我是否可以将日期计算为 case 语句,然后只在WHEN 语句。

代码有效:

SELECT 
     O.ID
     CASE 
       WHEN TO_DATE(SYSDATE) - TO_DATE(O.CREATED_AT) BETWEEN 1  AND 10 THEN 'start'
       WHEN TO_DATE(SYSDATE) - TO_DATE(O.CREATED_AT) BETWEEN 11  AND 15 THEN 'proccesing'
       WHEN TO_DATE(SYSDATE) - TO_DATE(O.CREATED_AT) BETWEEN 16  AND 30 THEN 'finish'
       ELSE 'expired'
     END AS State
FROM ORDER O
WHERE O.STATE > 2

下一个代码抛出下一个错误“SQL 错误 [923] [42000]: ORA-00923: FROM keyword not found where expected”

SELECT 
     O.ID
     CASE TO_DATE(SYSDATE) - TO_DATE(O.CREATED_AT) as totaldays
       WHEN totaldays BETWEEN 1  AND 10 THEN 'start'
       WHEN totaldays BETWEEN 11  AND 15 THEN 'proccesing'
       WHEN totaldays BETWEEN 16  AND 30 THEN 'finish'
       ELSE 'expired'
     END AS State
FROM ORDER O
WHERE O.STATE > 2

我的目标是每行计算一次,这比对每个“案例”句子进行计算更好吗?性能有没有区别?

有没有办法计算一次,然后评估结果?

【问题讨论】:

第二个不是有效的 SQL,所以它不是一个选项。坚持运行的代码。 在 SQL 表达式或内置函数中性能并非如此,因为大部分时间都花在读取、排序、连接和聚合数据上 O.ID 后面需要一个逗号... 不要使用to_date(sysdate); sysdate 已经是一个日期。我怀疑这同样适用于 created_at 列。如果列/变量已经是日期,则永远不需要转换为日期,实际上可能会发生非常难以发现的奇怪错误。 我正要说 :-) TO_DATE 存在将字符串转换为日期时间(Oracle 不恰当地调用 DATE)。也许你想要 TRUNC(SYSDATE)TRUNC(O.CREATED_AT) 代替。从日期时间中删除时间部分 【参考方案1】:

派生表中执行TO_DATE 的内容,这样您就可以节省一些输入,而且代码容易出错:

SELECT ID,
       CASE WHEN totaldays BETWEEN 1   AND 10 THEN 'start'
            WHEN totaldays BETWEEN 11  AND 15 THEN 'proccesing'
            WHEN totaldays BETWEEN 16  AND 30 THEN 'finish'
            ELSE 'expired'
       END AS State
FROM
(
  SELECT 
       O.ID,
       TRUNC(SYSDATE) - TRUNC(O.CREATED_AT) as totaldays 
  FROM ORDER O
  WHERE O.STATE > 2
) dt

顺便说一句,ORDER 是 SQL 保留字,因此表名必须限定为 "ORDER"。 (https://en.wikipedia.org/wiki/SQL_reserved_words.)

编辑: astentx 建议简化为:

SELECT ID,
       CASE WHEN totaldays <= 10 THEN 'start'
            WHEN totaldays <= 15 THEN 'proccesing'
            WHEN totaldays <= 30 THEN 'finish'
            ELSE 'expired'
       END AS State
FROM
(
  SELECT 
       O.ID,
       TRUNC(SYSDATE) - TRUNC(O.CREATED_AT) as totaldays 
  FROM ORDER O
  WHERE O.STATE > 2
) dt

【讨论】:

between 可以进一步缩短为&lt;= upper_boundary @astentx,当然......我会在答案中添加那个版本! 还有to_date(sysdate)...没有cmets) 你的意思是应该是sysdate - TO_DATE(O.CREATED_AT)? (我从未使用过 Oracle,我只是想向 OP 展示派生表的技巧......) 他们可能想要删除时间部分,以便从另一个日期中减去一个日期并获得完整天数(整数),因此:TRUNC(SYSDATE) - TRUNC(O.CREATED_AT) as totaldays

以上是关于比较两个日期Oracle的多案例的主要内容,如果未能解决你的问题,请参考以下文章

在oracle中比较两个日期

Oracle两个日期类型字段怎么比较大小

oracle数据库里两个字符型的日期数据怎样比较?

如果仅按日和月将两个日期与 Oracle SQL 进行比较

Oracle两个日期类型字段怎么比较大小

有没有更好的方法来编写这个处理比较两个不同列中的日期的 Oracle SQL?