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

Posted

技术标签:

【中文标题】在“WHERE”中的“CASE”语句中的“THEN”之后使用“Between”运算符【英文标题】:Using 'Between' operator after 'THEN' within 'CASE' statement within 'WHERE' 【发布时间】: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? 【参考方案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

以上是关于在“WHERE”中的“CASE”语句中的“THEN”之后使用“Between”运算符的主要内容,如果未能解决你的问题,请参考以下文章

带有 Exists 的 WHERE CASE WHEN THEN 语句

sql查询中case语句中的布尔值

SELECT 和 WHERE 中的 SQL CASE 用于选择行

where 子句 oracle 中的 case 语句

在 where 子句的 Case 语句中定义一个变量

如何在oracle sql中的where条件中使用case语句?