【问题标题】:Oracle Case in WHERE Clause with multiple conditions具有多个条件的 WHERE 子句中的 Oracle 案例
【发布时间】:2021-11-07 04:39:57
【问题描述】:

我正在尝试在 where 子句中传递 case 语句,但似乎我遗漏了一些东西,或者在我的场景中这是不可能的,下面是我的代码

代码解释“如果 sysdate 是星期天,我想检索过去 3 天的数据,否则取昨天的数据”

    FROM lea_nf1.lea_agreement_dtl c--, lea_nf1.LEA_GUARANTOR_HIRER_DTL d
   WHERE
            case when to_char(sysdate,'Day') = 'Sunday' then 
            to_char(C.DISBURSALDATE , 'mm') = to_char(sysdate-1, 'mm')
            and to_char(C.DISBURSALDATE , 'yyyy') = to_char(sysdate-1, 'yyyy')
            and C.DISBURSALDATE between trunc(sysdate-3) and trunc(sysdate-1)
            else 
            to_char(C.DISBURSALDATE , 'mm') = to_char(sysdate-1, 'mm')
            and (to_char(C.DISBURSALDATE , 'yyyy') = to_char(sysdate-1, 'yyyy')
            and C.DISBURSALDATE < sysdate end
ORDER BY C.DISBURSALDATE desc

下面是错误

ORA-00905:缺少关键字

【问题讨论】:

  • 跳过大小写表达式,改用正则AND/OR。
  • Oracle 没有布尔数据类型,这就是为什么您不能将 case 表达式评估为某些谓词的结果
  • 你确定你的逻辑是正确的(即使忽略代码)?如果是星期天,您想返回三天,如果不是只返回一天。既然是对一(不是对一),这是否意味着星期六也很特别?如果是这样,你不应该对星期六有不同的条件,而不仅仅是星期天吗?如果您告诉我们实际任务(而不仅仅是代码),我们可能会帮助您找到更简单、更优雅、更高效的解决方案。

标签: sql oracle select case


【解决方案1】:

如您所见,您不能像这样使用case 语句来构建where 子句。但是,您可以做的是使用逻辑运算符来获得所需的行为:

WHERE
    (to_char(sysdate,'Day') = 'Sunday' AND 
     to_char(C.DISBURSALDATE , 'mm') = to_char(sysdate-1, 'mm') AND
     to_char(C.DISBURSALDATE , 'yyyy') = to_char(sysdate-1, 'yyyy') AND
     C.DISBURSALDATE between trunc(sysdate-3) and trunc(sysdate-1)) OR
    (to_char(sysdate,'Day') != 'Sunday' AND
     to_char(C.DISBURSALDATE , 'mm') = to_char(sysdate-1, 'mm') AND
     to_char(C.DISBURSALDATE , 'yyyy') = to_char(sysdate-1, 'yyyy') AND
     C.DISBURSALDATE < sysdate)

这当然可以通过提取or运算符两边的共同条件来简化:

WHERE
    to_char(C.DISBURSALDATE , 'mm') = to_char(sysdate-1, 'mm') AND
    to_char(C.DISBURSALDATE , 'yyyy') = to_char(sysdate-1, 'yyyy') AND
    (to_char(sysdate,'Day') = 'Sunday' AND 
     C.DISBURSALDATE between trunc(sysdate-3) and trunc(sysdate-1)) OR
    (to_char(sysdate,'Day') != 'Sunday'  AND
     C.DISBURSALDATE < sysdate)

或者,如果你更进一步,任何C.DISBURSALDATEbetween trunc(sysdate-3) and trunc(sysdate-1) 也总是&lt; sysdate,所以:

WHERE
    to_char(C.DISBURSALDATE , 'mm') = to_char(sysdate-1, 'mm') AND
    to_char(C.DISBURSALDATE , 'yyyy') = to_char(sysdate-1, 'yyyy') AND
    C.DISBURSALDATE < sysdate AND
    (to_char(sysdate,'Day') != 'Sunday' OR
     C.DISBURSALDATE between trunc(sysdate-3) and trunc(sysdate-1))

【讨论】:

  • 感谢您的回复,但他们都没有工作我试图从周日到周五替换 Day,这样我就可以测试 hte 代码它在两者上都显示相同的结果
  • @Sulzehq 哎呀!忘记在or 运算符的另一侧添加to_char(sysdate,'Day') != 'Sunday'... 过失。
【解决方案2】:

CASE 语句返回一个不能作为 WHERE CONDITION itsef 评估的“列值”,但您可以根据 sysdate 将其用作值 1 或 3,然后在过滤条件中使用此值:

WHERE
TRUNC(C.DISBURSALDATE) >=
TRUNC(
    SYSDATE  - 
    (CASE WHEN to_char(sysdate,'Day') = 'Sunday' THEN 3 ELSE 1 END) -- this case will return 3 or 1, and use it to subtract from sysdate
    )
AND TRUNC(C.DISBURSALDATE) < TRUNC(SYSDATE) --this is just because I am not sure if your data has dates after today

此外,您不需要以下子句来过滤日期:

to_char(C.DISBURSALDATE , 'mm') = to_char(sysdate-1, 'mm') AND
to_char(C.DISBURSALDATE , 'yyyy') = to_char(sysdate-1, 'yyyy')

【讨论】:

  • 感谢我不得不稍微修改您的代码以使其完美运行..
猜你喜欢
  • 1970-01-01
  • 2013-07-09
  • 1970-01-01
  • 1970-01-01
  • 2016-06-16
  • 1970-01-01
  • 2019-06-03
  • 1970-01-01
  • 2012-08-24
相关资源
最近更新 更多