在“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 语句