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

时间:2014-02-12 15:57:20

标签: sql oracle

是否可以在WHERE子句中的CASE语句中使用运算符?例如,在下面的代码中,条件应该是(sysdate-12)和(sysdate-2)之间的pydate,如果它是星期二和pydate(sysdate-11)和(sysdate-1),如果它是星期二,依此类推。但以下不起作用。可能还有另一种写作方式。有人可以帮忙吗?

  select * from table_name
  where pricekey = 'JUF' and  
 case when to_char(to_date(sysdate,'DD-MON-YY'), 'DY')='MON' then pydate between to_date(sysdate-12,'DD-MON-YY') and to_date(sysdate-2,'DD-MON-YY')
 when to_char(to_date(sysdate,'DD-MON-YY'), 'DY')='TUE' then pydate between to_date(sysdate-11,'DD-MON-YY') and to_date(sysdate-1,'DD-MON-YY')
 else pydate='sysdate'
 end

3 个答案:

答案 0 :(得分:1)

您可以应用您尝试的逻辑,但不使用CASE。相反,您需要创建OR/AND的逻辑分组,以将BETWEEN与您案例中的其他匹配条件相结合。

这是因为CASE旨在返回一个值,而不是动态构造其中的SQL。

SELECT *
FROM  table_name
WHERE
  pricekey = 'JUF'
  AND (
    -- Condition 1
    (to_char(to_date(sysdate,'DD-MON-YY'), 'DY') = 'MON' AND pydate BETWEEN to_date(sysdate-12,'DD-MON-YY') AND to_date(sysdate-2,'DD-MON-YY'))
    -- Condition 2
    OR (to_char(to_date(sysdate,'DD-MON-YY'), 'DY')='TUE' AND pydate BETWEEN to_date(sysdate-11,'DD-MON-YY') AND to_date(sysdate-1,'DD-MON-YY'))
    -- ELSE case, matching neither of the previous 2
    OR (to_char(to_date(sysdate,'DD-MON-YY'), 'DY') NOT IN ('MON', 'TUE') AND pydate = 'sysdate')
  )

答案 1 :(得分:1)

使用case很难写。只是做:

where pricekey = 'JUF' and  
      ((to_char(to_date(sysdate,'DD-MON-YY'), 'DY') = 'MON' and
        pydate between to_date(sysdate-12,'DD-MON-YY') and to_date(sysdate-2,'DD-MON-YY')
       ) or
       (to_char(to_date(sysdate,'DD-MON-YY'), 'DY') = 'TUE' and
        pydate between to_date(sysdate-11,'DD-MON-YY') and to_date(sysdate-1,'DD-MON-YY')
       ) or
       (o_char(to_date(sysdate,'DD-MON-YY'), 'DY') not in ('MON', 'TUE') and
        pydate = trunc(sysdate)
       )
      )

注意,我还删除了“sysdate”周围的单引号,因此不会将其视为字符串。而且,我把它截断到只是没有时间的日期部分。

答案 2 :(得分:1)

首先,sysdate是一个日期,所以不要在它上面使用to_date。

其次,不要依赖日名。选择其他语言设置后,您的陈述可能不再有效。

然后pydate是约会。 sysdate是一个日期。不要将pydate与字符串'sysdate'进行比较,而是将其与sysdate进行比较。

您似乎也尝试使用to_date(sysdate-11,'DD-MON-YY')从sysdate中删除时间部分。用于删除日期时间的时间部分的函数是trunc。

然后case语句应该返回一个值。 SQL中没有布尔数据类型,因此您无法在内部计算表达式并返回结果。您将返回一个有效的数据类型,例如数字或字符串,您可以在外部进行比较,而不是这样做:

select * 
from table_name
where pricekey = 'JUF' and  
case 
  when to_char(sysdate, 'DY', 'NLS_DATE_LANGUAGE=AMERICAN')='MON' then
    case when pydate between trunc(sysdate)-12 and trunc(sysdate)-2 then 'GOOD' else 'BAD' end
  when to_char(sysdate, 'DY', 'NLS_DATE_LANGUAGE=AMERICAN')='TUE' then 
    case when pydate between trunc(sysdate)-11 and trunc(sysdate)-1 then 'GOOD' else 'BAD' end
  else 
    case when pydate = trunc(sysdate) then 'GOOD' else 'BAD' end
end = 'GOOD';

如果pydate可以有时间部分,你可能也想用trunc(pydate)替换pydate。

当然,您可以使用一些AND和OR以及括号而不是CASE语句来完成所有这些操作。这取决于你对你更具可读性。