ORA-00905:缺少关键字

时间:2015-02-09 10:05:10

标签: sql oracle case

我的表格包含以下列:

|blo|NotionalCurrency|Notional|Premiumcurrency|Basecurrency|Termcurrency|StructureName|Basemarketprice|Termmarketpriceprecent |Termmarketprice|

我想从这些获得blo,货币和价格。下面是我的SQL:

   select blo.opt,
  case
  when opt.premiumcurrency is not null and opt.structurename is not null  then currency = opt.premiumcurrency
      case
      when opt.notionalcurrency = opt.basecurrency and opt.premiumcurrency = opt.termcurrency then price = opt.termmarketpricepercent / opt.notional
      else
          case
             when opt.premiumcurrency = opt.basecurrency then price = opt.basemarketprice /100
             else
             price = opt.termmarketpriceprecent /100
             end
       end
   when price = 0 then price = 0.000001
   end
FROM interface opt
WHERE opt.notionalcurrency = opt.basecurrency and opt.premiumcurrency = opt.termcurrency;

但我收到错误:ORA-00905: missing keyword

基本上,下面的逻辑应该用于获取/派生SQL以获得三列:Blo,货币和价格:

If notional currency = base currency and premium currency=term currency Then
               Price =term market price/notional
               currency = notional currency
Else
               If notional currency = premium currency then
                              Price= base market price /100
                              currency = termcurrency
               else
                              Price=term market price percent /100
                              currency = notional
               end if
end if
if price=0 then 
price=0.000001
end if

4 个答案:

答案 0 :(得分:5)

您错过了初始案例陈述中的end。只需在when price = 0 then price = 0.000001

之后添加即可

答案 1 :(得分:2)

这里有很多问题。分解一下:

  case
  when opt.premiumcurrency is not null
    and opt.structurename is not null

where条件开始,opt.premiumcurrency不能为空,因此检查不会添加任何内容。

  then currency = opt.premiumcurrency

您无法在此处设置值;看起来你希望这是一个在最终输出中被标记为currency的表达式,正如Arka所示。

      case
      when opt.notionalcurrency = opt.basecurrency
        and opt.premiumcurrency = opt.termcurrency
      then price = opt.termmarketpricepercent / opt.notional

现在你正在寻找价格,而不是货币,所以这不是前一个案例条款的一部分;这意味着你现在应该有一个end as currency,。但是您也没有else条件,这意味着如果opt.structurename为空,您的货币表达式将为空;不清楚这是不是你想要的。

但是由于你的where子句,这两个条件都必须成立,这使得整个case变得多余。再次,您需要一个表达式别名,而不是尝试使用=设置值。

      else
          case
             when opt.premiumcurrency = opt.basecurrency
             then price = opt.basemarketprice /100
             else
             price = opt.termmarketpriceprecent /100
          end
       end

你已经在这里嵌套了一个案例,所以看起来你正试图直接转换if / elsif / else结构,而不考虑case的语义是如何实际工作的。当/ end可以是封闭的case的一部分时,不需要嵌套的case / end。但如上所述,第一个when条件必须始终为真,并且opt.premiumcurrency = opt.basecurrency也必须始终为真,因此所有这些都是多余的。

   when price = 0 then price = 0.000001

这只是漂浮在那里,所以这需要是外壳或解码,或者如果值永远不会是负值,则可能是least()

因此,根据您显示的where条件,可以将其缩小为:

select opt.blo,
  case
    when opt.structurename is not null then opt.premiumcurrency
  end as currency,
  case
    when opt.termmarketpricepercent = 0 then 0.000001
    else opt.termmarketpricepercent / opt.notional
  end as price
from interface opt
where opt.notionalcurrency = opt.basecurrency
and opt.premiumcurrency = opt.termcurrency;

如果where子句是临时的,并且您需要更通用的查询,那么它仍然比您制作它更简单:

select opt.blo,
  case
    when opt.premiumcurrency is not null
      and opt.structurename is not null 
        then opt.premiumcurrency
    end as currency, -- still no 'else' so null if structurename is null
    decode (
      case
        when opt.notionalcurrency = opt.basecurrency
          and opt.premiumcurrency = opt.termcurrency
          then opt.termmarketpricepercent / opt.notional
        when opt.premiumcurrency = opt.basecurrency
          then opt.basemarketprice /100
        else opt.termmarketpricepercent /100
      end, 0, 0.000001) as price
from interface opt;

(我已经将blo.opt交换为opt.blo,正如Sathya发现的那样,并且还修复了至少一个列引用中的拼写错误...)

根据您的最新修改,您希望根据相同的条件挑选货币和价格,这在原始查询中并不明显。每个案例只能评估一个值,因此您需要在两个表达式中重复这些条件,一个用于货币,一个用于价格;如果它是零,你仍然想要改变价格。再假设where是暂时的:

select opt.blo,
  case
    when opt.notionalcurrency = opt.basecurrency
      and opt.premiumcurrency = opt.termcurrency
      then opt.notionalcurrency
    when opt.notionalcurrency = opt.premiumcurrency
      then opt.termcurrency
    else opt.notionalcurrency
  end as currency,
  decode (
    case
      when opt.notionalcurrency = opt.basecurrency
        and opt.premiumcurrency = opt.termcurrency
        then opt.termmarketpricepercent / opt.notional
      when opt.notionalcurrency = opt.premiumcurrency
        then opt.basemarketprice / 100
      else opt.termmarketpricepercent / 100
    end, 0, 0.000001) as price
from interface opt;

价格计算与之前相同,货币表达式已更改为匹配相同的逻辑。你现在似乎已经失去了structurename支票。并且有一个潜在的假设,即没有任何货币值是真的。

SQL Fiddle包含部​​分表而没有数据,只是为了显示查询没有错误。

答案 2 :(得分:1)

试试这个:

SELECT opt.blo,
       CASE
         WHEN (opt.premiumcurrency IS NOT NULL
           AND opt.structurename IS NOT NULL) THEN
           currency = opt.premiumcurrency
       END,
       CASE
         WHEN (opt.notionalcurrency = opt.basecurrency
           AND opt.premiumcurrency = opt.termcurrency) THEN
           price = opt.termmarketpricepercent / opt.notional
         WHEN price = 0 THEN
           price = 0.000001
         WHEN opt.premiumcurrency = opt.basecurrency THEN
           price = opt.basemarketprice / 100
         ELSE
           price = opt.termmarketpriceprecent / 100
       END
  FROM interface opt
 WHERE opt.notionalcurrency = opt.basecurrency
   AND opt.premiumcurrency = opt.termcurrency;

答案 3 :(得分:0)

我对此查询有几点了解:

  1. 根据我的理解,opt是表的别名,要获取属性,你应该写opt.blo而不是blo.opt。
  2. 案例陈述应包含案例值,例如您使用案例陈述的列名
  3. 我试图修改代码。未编译,因此可能存在语法错误。检查一下。

      select opt.blo,
      case opt.currency
      when opt.premiumcurrency is not null and opt.structurename is not null
      then opt.premiumcurrency
      end as Currency,
      case opt.price
      when opt.notionalcurrency = opt.basecurrency and opt.premiumcurrency = opt.termcurrency then opt.termmarketpricepercent / opt.notional
      when opt.premiumcurrency = opt.basecurrency then opt.basemarketprice /100
      when price = 0 then price = 0.000001
      else
      opt.termmarketpriceprecent /100
      end as Price,
    FROM interface opt
    WHERE opt.notionalcurrency = opt.basecurrency and opt.premiumcurrency = opt.termcurrency;