在“ WHERE”中“ CASE”语句中的“ THEN”之后使用“ Between”运算符

时间:2018-06-29 18:26:45

标签: sql oracle

我正在尝试做这样的事情

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àligne 182,殖民地42

2 个答案:

答案 0 :(得分:4)

我会这样写:

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。

答案 1 :(得分:0)

您不能将逻辑放在这样的大小写结果中,如果可以,则将布尔结果与数值结果混合在一起。

如果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 ..提供一个默认值,该默认值在该范围内,这可能最终将完成比实际需要更多的工作。

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