【问题标题】:Using 'Between' operator after 'THEN' within 'CASE' statement within 'WHERE'在“WHERE”中的“CASE”语句中的“THEN”之后使用“Between”运算符
【发布时间】:2018-06-29 18:26:45
【问题描述】:

我正在尝试做这样的事情

select *
from m
where CASE WHEN x=1 THEN trunc(m.ATT_DATE) between '18-01-01' AND '18-12-31'
WHEN x=2 THEN trunc(m.main_date) between '18-01-01' AND '18-12-31'
ELSE 1 END = 1;

x 是一个变量

我收到此错误 ORA-00905: mot-clé 不存在 00905. 00000 - “缺少关键字” *原因:
*行动: Erreur à la ligne 182,科隆 42

【问题讨论】:

  • THEN 后面必须跟一个表达式(例如 END 关键字后面的常量 1)。它后面不能跟一个条件。条件应该是什么?用文字描述它。应该是“x = 1 and ATT_DATE between ....”还是“x = 2 and ATT_DATE between....”或“x not in (1, 2)”?如果是这种情况(或者类似的情况),那么就这样写吧。你为什么想要/需要CASE construct?

标签: sql oracle


【解决方案1】:

我会这样写:

select m.*
from m
where (x = 1 and trunc(m.ATT_DATE) between date '2018-01-01' and date '2018-12-31') or
      (x = 2 and trunc(m.main_date) between date '2018-01-01' and date '2018-12-31') or
      (x not in (1, 2));

注意事项:

  • 通常,case 表达式可以替换为 where 子句中的简单布尔逻辑。
  • 您的查询存在的一个问题是 Oracle 无法识别布尔值,因此 then 子句无法返回布尔表达式。
  • 应使用date 关键字引入日期常量。
  • 日期常量应使用 ANSI/ISO 标准格式,例如 YYYY-MM-DD。

【讨论】:

    【解决方案2】:

    你不能把逻辑放在这样的案例结果中,如果可以的话,你会得到一个布尔结果和一个数字结果。

    如果x 既不是 1 也不是 2,取决于您想要发生的情况,您可以在这种情况下使用以下任一方法返回任何内容:

    select *
    from m
    where (x=1 and trunc(m.att_date) between date '2018-01-01' and date '2018-12-31')
      or (x=2 and trunc(m.main_date) between date '2018-01-01' and date '2018-12-31');
    
    select *
    from m
    where (x=1 and m.att_date >= date '2018-01-01' and m.att_date < date '2019-01-01')
      or (x=2 and m.main_date >= date '2018-01-01' and m.main_date < date '2019-01-01');
    
    select *
    from m
    where case when x=1 then m.att_date when x=2 then m.main_date end >= date '2018-01-01'
      and case when x=1 then m.att_date when x=2 then m.main_date end < date '2019-01-01';
    

    最后两个与完整的日期/时间范围进行比较,而不是使用trunc(),这将阻止使用这些列上的任何索引;或者如果您想在x 不是 1 或 2 时包含所有行:

    select *
    from m
    where (x=1 and trunc(m.att_date) between date '2018-01-01' and date '2018-12-31')
      or (x=2 and trunc(m.main_date) between date '2018-01-01' and date '2018-12-31')
      or x not in (1,2);
    
    select *
    from m
    where (x=1 and m.att_date >= date '2018-01-01' and m.att_date < date '2019-01-01')
      or (x=2 and m.main_date >= date '2018-01-01' and m.main_date < date '2019-01-01')
      or x not in (1,2);
    
    select *
    from m
    where case when x=1 then m.att_date when x=2 then m.main_date
        else date '2018-01-01' end >= date '2018-01-01'
      and case when x=1 then m.att_date when x=2 then m.main_date
        else date '2018-01-01' end < date '2019-01-01';
    

    前两个添加了对x 的显式检查(第一个是@Gordon 正在做的......);第三个使用case .. else .. 提供范围内的默认值,这可能最终会做比实际需要更多的工作。

    我个人会在每种情况下使用中间那个。

    【讨论】:

    • 谢谢大家,它现在正在工作我使用过:(x = 1 and trunc(m.ATT_DATE) between date '2018-01-01' and date '2018-12-31') 或(x = 2 and trunc(m.main_date) between date '2018-01-01' and date '2018-12-31') 而不是 CASE WHEN x=1 THEN trunc(m.ATT_DATE) between '18-01- 01' AND '18-12-31' WHEN x=2 THEN trunc(m.main_date) between '18-01-01' AND '18-12-31' ELSE 1 END = 1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-21
    • 2019-06-04
    相关资源
    最近更新 更多